Compare commits
52 Commits
Author | SHA1 | Date | |
---|---|---|---|
b4cad9c745 | |||
100c5612dc | |||
b8e0100bdf | |||
137db42446
|
|||
956d2009eb | |||
ec66da8b5e | |||
0555ee0db7
|
|||
837b487281
|
|||
9a0f2c062c
|
|||
![]() |
6e9c69c2a8 | ||
f0cef81b5e | |||
d8160effd0
|
|||
18da07763c
|
|||
3c448f2290
|
|||
cadc7e223f | |||
e1baca7940 | |||
c2e0cf65a8 | |||
a3d0408d6f | |||
9ca6931bb8 | |||
f22eff1f72 | |||
11e097d696 | |||
f7ecb45774 | |||
00a7328e3a | |||
c39229a28b | |||
00c56b0888
|
|||
15898d54c2
|
|||
6d5ed42e60 | |||
92a8e224ef | |||
669ceed2a9
|
|||
778d30ae26 | |||
d2212da456
|
|||
a3dfe35df6
|
|||
da6623741c
|
|||
abea8f0856
|
|||
1624a84cf1 | |||
ba852831aa
|
|||
5de9ad3a54
|
|||
4c8ce23e8a
|
|||
2be5f5d320
|
|||
c428f306ca
|
|||
3dde713c91
|
|||
3280446c7e
|
|||
a408e22a68 | |||
1b71cda403 | |||
eb8dbbd7f9 | |||
abc361faf0
|
|||
d5d3eef5f8 | |||
9f553e57d2 | |||
35af19f82e | |||
c113868b58 | |||
51c76e1b2a | |||
c58f66ff4a |
52
.gitea/workflows/build.yml
Normal file
52
.gitea/workflows/build.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
name: .NET Build and Publish to Gitea
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: '*'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: dotnet
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Download Dalamud
|
||||
run: |
|
||||
mkdir -p $HOME/.xlcore/dalamud/Hooks/dev/
|
||||
curl -L https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -o latest.zip
|
||||
unzip -o latest.zip -d $HOME/.xlcore/dalamud/Hooks/dev/
|
||||
|
||||
- name: Build project
|
||||
run: dotnet build --no-restore --configuration Release --nologo
|
||||
|
||||
- name: Publish Windows executable
|
||||
run: dotnet publish -c Release -r win-x64 --self-contained true -o ./publish
|
||||
|
||||
- name: Archive published files
|
||||
run: zip -r SnowcloakClient.zip ./publish/*
|
||||
|
||||
- name: Create Gitea release
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.BUILD_SNOWCLOAK_CLIENT }}
|
||||
run: |
|
||||
API_URL="https://git.snowcloak-sync.com/api/v1/repos/Eauldane/SnowcloakClient/releases"
|
||||
TAG="v$(date +%Y%m%d%H%M)"
|
||||
# Create release
|
||||
RELEASE_ID=$(curl -s -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-d "{\"tag_name\":\"$TAG\",\"name\":\"Automated Build $TAG\",\"body\":\"Automated build artifact\"}" \
|
||||
$API_URL | jq -r '.id')
|
||||
echo "Release ID: $RELEASE_ID"
|
||||
# Upload asset
|
||||
curl -s -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-F "name=SnowcloakClient.zip" \
|
||||
-F "attachment=@SnowcloakClient.zip" \
|
||||
"$API_URL/$RELEASE_ID/assets"
|
@@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnowcloakSync", "SnowcloakSync\SnowcloakSync.csproj", "{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -36,6 +38,14 @@ Global
|
||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -8,6 +8,6 @@ public static class ConfigurationExtensions
|
||||
{
|
||||
return configuration.AcceptedAgreement && configuration.InitialScanComplete
|
||||
&& !string.IsNullOrEmpty(configuration.CacheFolder)
|
||||
&& Directory.Exists(configuration.CacheFolder) && configuration.AcceptedTOSVersion == configuration.ExpectedTOSVersion;
|
||||
&& Directory.Exists(configuration.CacheFolder);
|
||||
}
|
||||
}
|
@@ -7,6 +7,7 @@ namespace MareSynchronos.MareConfiguration.Configurations;
|
||||
[Serializable]
|
||||
public class MareConfig : IMareConfiguration
|
||||
{
|
||||
public bool SortSyncshellsByVRAM { get; set; } = false;
|
||||
public int ExpectedTOSVersion = 2;
|
||||
public int AcceptedTOSVersion { get; set; } = 0;
|
||||
public bool AcceptedAgreement { get; set; } = false;
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Dalamud.NET.Sdk/13.0.0">
|
||||
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Snowcloak</AssemblyName>
|
||||
<Version>0.2.0</Version>
|
||||
<PackageProjectUrl>https://github.com/Eauldane/SnowcloakClient/</PackageProjectUrl>
|
||||
<Version>0.2.4</Version>
|
||||
<PackageProjectUrl>https://git.snowcloak-sync.com/Eauldane/SnowcloakClient/</PackageProjectUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -14,10 +14,12 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Chaos.NaCl.Standard" Version="1.0.0" />
|
||||
<PackageReference Include="Downloader" Version="3.3.4" />
|
||||
<PackageReference Include="Downloader" Version="4.0.3" />
|
||||
<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.212">
|
||||
<PackageReference Include="MessagePack" Version="3.1.4" />
|
||||
<PackageReference Include="MessagePack.Annotations" Version="3.1.4" />
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.213">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -29,6 +31,8 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
|
||||
<PackageReference Update="DalamudPackager" Version="13.1.0" />
|
||||
<PackageReference Include="System.IO.Pipelines" Version="9.0.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="Exists('.\Penumbra.Api\Penumbra.Api.csproj')">
|
||||
@@ -54,6 +58,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
||||
<ProjectReference Include="..\SnowcloakSync\SnowcloakSync.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -235,11 +235,17 @@ public class Pair : DisposableMediatorSubscriberBase
|
||||
{
|
||||
string? noteOrName = GetNoteOrName();
|
||||
|
||||
if (noteOrName != null)
|
||||
if (_mareConfig.Current.SortSyncshellsByVRAM)
|
||||
{
|
||||
return($"0{LastAppliedApproximateVRAMBytes}");
|
||||
}
|
||||
else if (noteOrName != null) {
|
||||
return $"0{noteOrName}";
|
||||
else
|
||||
}
|
||||
else {
|
||||
return $"9{UserData.AliasOrUID}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetPlayerNameHash()
|
||||
{
|
||||
|
@@ -14,8 +14,9 @@ namespace MareSynchronos.Services;
|
||||
|
||||
public sealed class CommandManagerService : IDisposable
|
||||
{
|
||||
private const string _commandName = "/sync";
|
||||
private const string _commandName = "/snow";
|
||||
private const string _commandName2 = "/snowcloak";
|
||||
private const string _commandName3 = "/sync";
|
||||
|
||||
private const string _ssCommandPrefix = "/ss";
|
||||
|
||||
@@ -48,6 +49,10 @@ public sealed class CommandManagerService : IDisposable
|
||||
{
|
||||
HelpMessage = "Opens the Snowcloak UI"
|
||||
});
|
||||
_commandManager.AddHandler(_commandName3, new CommandInfo(OnCommand)
|
||||
{
|
||||
HelpMessage = "Opens the Snowcloak UI"
|
||||
});
|
||||
|
||||
// Lazy registration of all possible /ss# commands which tbf is what the game does for linkshells anyway
|
||||
for (int i = 1; i <= ChatService.CommandMaxNumber; ++i)
|
||||
|
@@ -9,6 +9,6 @@
|
||||
"customization"
|
||||
],
|
||||
"IconUrl": "https://raw.githubusercontent.com/Eauldane/SnowcloakClient/refs/heads/main/MareSynchronos/images/logo.png",
|
||||
"RepoUrl": "https://github.com/Eauldane/SnowcloakClient",
|
||||
"RepoUrl": "https://git.snowcloak-sync.com/Eauldane/SnowcloakClient",
|
||||
"CanUnloadAsync": true
|
||||
}
|
||||
|
@@ -1054,7 +1054,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
|
||||
_configService.Current.OpenMareHubOnGposeStart = openInGpose;
|
||||
_configService.Save();
|
||||
}
|
||||
_uiSharedService.DrawHelpText("This will automatically open the import menu when loading into Gpose. If unchecked you can open the menu manually with /sync gpose");
|
||||
_uiSharedService.DrawHelpText("This will automatically open the import menu when loading into Gpose. If unchecked you can open the menu manually with /snow gpose");
|
||||
bool downloadDataOnConnection = _configService.Current.DownloadMcdDataOnConnection;
|
||||
if (ImGui.Checkbox("Download Online Character Data on connecting", ref downloadDataOnConnection))
|
||||
{
|
||||
|
@@ -105,7 +105,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
protected override void DrawInternal()
|
||||
{
|
||||
if (_serverManager.CurrentApiUrl.Equals(ApiController.SnowcloakServiceUri, StringComparison.Ordinal))
|
||||
UiSharedService.AccentColor = new(0.4275f, 0.6863f, 1f, 1f);
|
||||
UiSharedService.AccentColor = SnowcloakSync.Utils.Colours._snowcloakOnline;
|
||||
else
|
||||
UiSharedService.AccentColor = ImGuiColors.ParsedGreen;
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ImGui.GetStyle().WindowPadding.Y - 1f * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.Y);
|
||||
@@ -362,13 +362,14 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY();
|
||||
var users = GetFilteredUsers().OrderBy(u => u.GetPairSortKey(), StringComparer.Ordinal);
|
||||
|
||||
var onlineUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline || u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var onlineUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline && !u.IsVisible && (!u.UserPair!.OtherPermissions.IsPaused() && !u.UserPair!.OwnPermissions.IsPaused()))).Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var pausedUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.UserPair!.OtherPermissions.IsPaused() || u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Paused" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var visibleUsers = users.Where(u => u.IsVisible).Select(c => new DrawUserPair("Visible" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var offlineUsers = users.Where(u => !u.UserPair!.OtherPermissions.IsPaired() || (!u.IsOnline && !u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Offline" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var offlineUsers = users.Where(u => !u.UserPair!.OtherPermissions.IsPaired() || !u.IsOnline && (!u.UserPair!.OwnPermissions.IsPaused() && !u.UserPair.OtherPermissions.IsPaused())).Select(c => new DrawUserPair("Offline" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
|
||||
ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false);
|
||||
|
||||
_pairGroupsUi.Draw(visibleUsers, onlineUsers, offlineUsers);
|
||||
_pairGroupsUi.Draw(visibleUsers, onlineUsers, pausedUsers, offlineUsers);
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
@@ -387,7 +388,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(new Vector4(0.675f, 0.985f, 1f, 1f), userCount);
|
||||
ImGui.SameLine();
|
||||
if (!printShard) ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Users Online");
|
||||
|
@@ -20,6 +20,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
private readonly GroupPairFullInfoDto _fullInfoDto;
|
||||
private readonly GroupFullInfoDto _group;
|
||||
private readonly CharaDataManager _charaDataManager;
|
||||
public long VRAMUsage { get; set; }
|
||||
|
||||
public DrawGroupPair(string id, Pair entry, ApiController apiController,
|
||||
MareMediator mareMediator, GroupFullInfoDto group, GroupPairFullInfoDto fullInfoDto,
|
||||
@@ -80,6 +81,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
}
|
||||
if (_pair.LastAppliedDataBytes >= 0)
|
||||
{
|
||||
|
||||
presenceText += UiSharedService.TooltipSeparator;
|
||||
presenceText += ((!_pair.IsVisible) ? "(Last) " : string.Empty) + "Mods Info" + Environment.NewLine;
|
||||
presenceText += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
||||
@@ -127,6 +129,9 @@ public class DrawGroupPair : DrawPairBase
|
||||
|
||||
protected override float DrawRightSide(float textPosY, float originalY)
|
||||
{
|
||||
var pauseIcon = _pair.IsPaused ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
||||
var pauseIconSize = _uiSharedService.GetIconButtonSize(pauseIcon);
|
||||
var spacingX = ImGui.GetStyle().ItemSpacing.X;
|
||||
var entryUID = _fullInfoDto.UserAliasOrUID;
|
||||
var entryIsMod = _fullInfoDto.GroupPairStatusInfo.IsModerator();
|
||||
var entryIsOwner = string.Equals(_pair.UserData.UID, _group.OwnerUID, StringComparison.Ordinal);
|
||||
@@ -145,19 +150,27 @@ public class DrawGroupPair : DrawPairBase
|
||||
bool showInfo = (individualAnimDisabled || individualSoundsDisabled || animDisabled || soundsDisabled);
|
||||
bool showPlus = _pair.UserPair == null;
|
||||
bool showBars = (userIsOwner || (userIsModerator && !entryIsMod && !entryIsOwner)) || !_pair.IsPaused;
|
||||
|
||||
bool showPause = true;
|
||||
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
||||
var permIcon = (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled) ? FontAwesomeIcon.ExclamationTriangle
|
||||
: ((soundsDisabled || animDisabled || vfxDisabled) ? FontAwesomeIcon.InfoCircle : FontAwesomeIcon.None);
|
||||
var runningIconWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X;
|
||||
var infoIconWidth = UiSharedService.GetIconSize(permIcon).X;
|
||||
var plusButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X;
|
||||
var pauseButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X;
|
||||
|
||||
var barButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars).X;
|
||||
var barButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
|
||||
|
||||
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth();
|
||||
var rightSidePos = windowEndX - barButtonSize.X;
|
||||
|
||||
|
||||
var pos = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() + spacing
|
||||
- (showShared ? (runningIconWidth + spacing) : 0)
|
||||
- (showInfo ? (infoIconWidth + spacing) : 0)
|
||||
- (showPlus ? (plusButtonWidth + spacing) : 0)
|
||||
- (showPause ? (pauseButtonWidth + spacing) : 0)
|
||||
- (showBars ? (barButtonWidth + spacing) : 0);
|
||||
|
||||
ImGui.SameLine(pos);
|
||||
@@ -264,6 +277,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
|
||||
if (showPlus)
|
||||
{
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
@@ -275,7 +289,25 @@ public class DrawGroupPair : DrawPairBase
|
||||
UiSharedService.AttachToolTip("Pair with " + entryUID + " individually");
|
||||
ImGui.SameLine();
|
||||
}
|
||||
if (showPause)
|
||||
{
|
||||
//rightSidePos -= pauseIconSize.X + spacingX;
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
|
||||
if (_uiSharedService.IconButton(pauseIcon))
|
||||
{
|
||||
var perm = _pair.UserPair!.OwnPermissions;
|
||||
perm.SetPaused(!perm.IsPaused());
|
||||
_ = _apiController.UserSetPairPermissions(new(_pair.UserData, perm));
|
||||
|
||||
}
|
||||
|
||||
UiSharedService.AttachToolTip(!_fullInfoDto.GroupUserPermissions.IsPaused()
|
||||
? "Pause pairing with " + entryUID
|
||||
: "Resume pairing with " + entryUID);
|
||||
ImGui.SameLine();
|
||||
|
||||
}
|
||||
if (showBars)
|
||||
{
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
@@ -285,7 +317,6 @@ public class DrawGroupPair : DrawPairBase
|
||||
ImGui.OpenPopup("Popup");
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.BeginPopup("Popup"))
|
||||
{
|
||||
if ((userIsModerator || userIsOwner) && !(entryIsMod || entryIsOwner))
|
||||
|
@@ -19,6 +19,7 @@ public class DrawUserPair : DrawPairBase
|
||||
protected readonly MareMediator _mediator;
|
||||
private readonly SelectGroupForPairUi _selectGroupForPairUi;
|
||||
private readonly CharaDataManager _charaDataManager;
|
||||
public long VramUsage { get; set; }
|
||||
|
||||
public DrawUserPair(string id, Pair entry, UidDisplayHandler displayHandler, ApiController apiController,
|
||||
MareMediator mareMediator, SelectGroupForPairUi selectGroupForPairUi,
|
||||
@@ -51,26 +52,27 @@ public class DrawUserPair : DrawPairBase
|
||||
{
|
||||
connectionIcon = FontAwesomeIcon.PauseCircle;
|
||||
connectionText = "Pairing status with " + _pair.UserData.AliasOrUID + " is paused";
|
||||
connectionColor = ImGuiColors.DalamudYellow;
|
||||
connectionColor = ImGuiColors.DalamudGrey;
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionIcon = FontAwesomeIcon.Check;
|
||||
connectionIcon = FontAwesomeIcon.Snowflake;
|
||||
connectionText = "You are paired with " + _pair.UserData.AliasOrUID;
|
||||
connectionColor = ImGuiColors.ParsedGreen;
|
||||
connectionColor = _pair.IsOnline ? SnowcloakSync.Utils.Colours._snowcloakOnline : ImGuiColors.DalamudGrey;
|
||||
}
|
||||
|
||||
ImGui.SetCursorPosY(textPosY);
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
UiSharedService.ColorText(connectionIcon.ToIconString(), connectionColor);
|
||||
ImGui.PopFont();
|
||||
UiSharedService.AttachToolTip(connectionText);
|
||||
if (_pair is { IsOnline: true, IsVisible: true })
|
||||
if (!_pair.IsVisible)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosY(textPosY);
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), ImGuiColors.ParsedGreen);
|
||||
UiSharedService.ColorText(connectionIcon.ToIconString(), connectionColor);
|
||||
ImGui.PopFont();
|
||||
UiSharedService.AttachToolTip(connectionText);
|
||||
}
|
||||
if (_pair is { IsOnline: true, IsVisible: true })
|
||||
{
|
||||
ImGui.SetCursorPosY(textPosY);
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), SnowcloakSync.Utils.Colours._snowcloakOnline);
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
_mediator.Publish(new TargetPairMessage(_pair));
|
||||
@@ -84,6 +86,7 @@ public class DrawUserPair : DrawPairBase
|
||||
visibleTooltip += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
||||
if (_pair.LastAppliedApproximateVRAMBytes >= 0)
|
||||
{
|
||||
VramUsage = _pair.LastAppliedApproximateVRAMBytes;
|
||||
visibleTooltip += Environment.NewLine + "Approx. VRAM Usage: " + UiSharedService.ByteToString(_pair.LastAppliedApproximateVRAMBytes, true);
|
||||
}
|
||||
if (_pair.LastAppliedDataTris >= 0)
|
||||
@@ -97,6 +100,8 @@ public class DrawUserPair : DrawPairBase
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override float DrawRightSide(float textPosY, float originalY)
|
||||
{
|
||||
var pauseIcon = _pair.UserPair!.OwnPermissions.IsPaused() ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
||||
|
@@ -418,16 +418,29 @@ internal sealed class GroupPanel
|
||||
ImGui.Indent(20);
|
||||
if (_expandedGroupState[groupDto.GID])
|
||||
{
|
||||
var sortedPairs = pairsInGroup
|
||||
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||
.ThenBy(u => u.GetPairSortKey(), StringComparer.OrdinalIgnoreCase);
|
||||
IOrderedEnumerable<Pair> sortedPairs;
|
||||
if (!_mareConfig.Current.SortSyncshellsByVRAM)
|
||||
{
|
||||
sortedPairs = pairsInGroup
|
||||
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||
.ThenBy(u => u.GetPairSortKey(), StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
sortedPairs = pairsInGroup
|
||||
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||
.ThenByDescending(u => u.LastAppliedApproximateVRAMBytes);
|
||||
}
|
||||
|
||||
var visibleUsers = new List<DrawGroupPair>();
|
||||
var onlineUsers = new List<DrawGroupPair>();
|
||||
var offlineUsers = new List<DrawGroupPair>();
|
||||
|
||||
|
||||
foreach (var pair in sortedPairs)
|
||||
{
|
||||
var drawPair = new DrawGroupPair(
|
||||
@@ -453,6 +466,8 @@ internal sealed class GroupPanel
|
||||
ImGui.TextUnformatted("Visible");
|
||||
ImGui.Separator();
|
||||
_uidDisplayHandler.RenderPairList(visibleUsers);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (onlineUsers.Count > 0)
|
||||
|
@@ -28,15 +28,15 @@ public class PairGroupsUi
|
||||
_uiSharedService = uiSharedService;
|
||||
}
|
||||
|
||||
public void Draw<T>(List<T> visibleUsers, List<T> onlineUsers, List<T> offlineUsers) where T : DrawPairBase
|
||||
public void Draw<T>(List<T> visibleUsers, List<T> onlineUsers, List<T> pausedUsers, List<T> offlineUsers) where T : DrawPairBase
|
||||
{
|
||||
// Only render those tags that actually have pairs in them, otherwise
|
||||
// we can end up with a bunch of useless pair groups
|
||||
var tagsWithPairsInThem = _tagHandler.GetAllTagsSorted();
|
||||
var allUsers = onlineUsers.Concat(offlineUsers).ToList();
|
||||
var allUsers = onlineUsers.Concat(offlineUsers).Concat(pausedUsers).ToList();
|
||||
if (typeof(T) == typeof(DrawUserPair))
|
||||
{
|
||||
DrawUserPairs(tagsWithPairsInThem, allUsers.Cast<DrawUserPair>().ToList(), visibleUsers.Cast<DrawUserPair>(), onlineUsers.Cast<DrawUserPair>(), offlineUsers.Cast<DrawUserPair>());
|
||||
DrawUserPairs(tagsWithPairsInThem, allUsers.Cast<DrawUserPair>().ToList(), visibleUsers.Cast<DrawUserPair>(), onlineUsers.Cast<DrawUserPair>(), pausedUsers.Cast<DrawUserPair>(), offlineUsers.Cast<DrawUserPair>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +91,19 @@ public class PairGroupsUi
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCategory(string tag, IEnumerable<DrawPairBase> onlineUsers, IEnumerable<DrawPairBase> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null)
|
||||
private void DrawCategory(string tag, IEnumerable<DrawPairBase> onlineUsers, IEnumerable<DrawPairBase> pausedUsers, IEnumerable<DrawPairBase> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null)
|
||||
{
|
||||
IEnumerable<DrawPairBase> usersInThisTag;
|
||||
HashSet<string>? otherUidsTaggedWithTag = null;
|
||||
bool isSpecialTag = false;
|
||||
int visibleInThisTag = 0;
|
||||
if (tag is TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag or TagHandler.CustomUnpairedTag)
|
||||
|
||||
if (tag is TagHandler.CustomPausedTag)
|
||||
{
|
||||
usersInThisTag = pausedUsers;
|
||||
isSpecialTag = true;
|
||||
}
|
||||
else if (tag is TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag or TagHandler.CustomUnpairedTag)
|
||||
{
|
||||
usersInThisTag = onlineUsers;
|
||||
isSpecialTag = true;
|
||||
@@ -113,14 +119,13 @@ public class PairGroupsUi
|
||||
|
||||
if (isSpecialTag && !usersInThisTag.Any()) return;
|
||||
|
||||
DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), otherUidsTaggedWithTag?.Count);
|
||||
DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), pausedUsers.Count(), otherUidsTaggedWithTag?.Count);
|
||||
if (!isSpecialTag)
|
||||
{
|
||||
using (ImRaii.PushId($"group-{tag}-buttons")) DrawButtons(tag, allUsers.Cast<DrawUserPair>().Where(p => otherUidsTaggedWithTag!.Contains(p.UID)).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Avoid uncomfortably close group names
|
||||
if (!_tagHandler.IsTagOpen(tag))
|
||||
{
|
||||
var size = ImGui.CalcTextSize("").Y + ImGui.GetStyle().FramePadding.Y * 2f;
|
||||
@@ -151,18 +156,19 @@ public class PairGroupsUi
|
||||
UiSharedService.AttachToolTip($"Delete Group {tag} (Will not delete the pairs)" + Environment.NewLine + "Hold CTRL to delete");
|
||||
}
|
||||
|
||||
private void DrawName(string tag, bool isSpecialTag, int visible, int online, int? total)
|
||||
private void DrawName(string tag, bool isSpecialTag, int visible, int online, int paused, int? total)
|
||||
{
|
||||
string displayedName = tag switch
|
||||
{
|
||||
TagHandler.CustomUnpairedTag => "Unpaired",
|
||||
TagHandler.CustomOfflineTag => "Offline",
|
||||
TagHandler.CustomOnlineTag => _mareConfig.Current.ShowOfflineUsersSeparately ? "Online/Paused" : "Contacts",
|
||||
TagHandler.CustomOnlineTag => _mareConfig.Current.ShowOfflineUsersSeparately ? "Online" : "Contacts",
|
||||
TagHandler.CustomPausedTag => "Paused",
|
||||
TagHandler.CustomVisibleTag => "Visible",
|
||||
_ => tag
|
||||
};
|
||||
|
||||
string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{total} Pairs)" : $"{displayedName} ({online} Pairs)";
|
||||
string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{paused}/{total} Pairs)" : $"{displayedName} ({online} Pairs)";
|
||||
|
||||
// FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight
|
||||
var icon = _tagHandler.IsTagOpen(tag) ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight;
|
||||
@@ -184,7 +190,8 @@ public class PairGroupsUi
|
||||
ImGui.TextUnformatted($"Group {tag}");
|
||||
ImGui.Separator();
|
||||
ImGui.TextUnformatted($"{visible} Pairs visible");
|
||||
ImGui.TextUnformatted($"{online} Pairs online/paused");
|
||||
ImGui.TextUnformatted($"{online} Pairs online");
|
||||
ImGui.TextUnformatted($"{paused} Pairs paused");
|
||||
ImGui.TextUnformatted($"{total} Pairs total");
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
@@ -197,39 +204,45 @@ public class PairGroupsUi
|
||||
ImGui.Separator();
|
||||
}
|
||||
|
||||
private void DrawUserPairs(List<string> tagsWithPairsInThem, List<DrawUserPair> allUsers, IEnumerable<DrawUserPair> visibleUsers, IEnumerable<DrawUserPair> onlineUsers, IEnumerable<DrawUserPair> offlineUsers)
|
||||
private void DrawUserPairs(List<string> tagsWithPairsInThem, List<DrawUserPair> allUsers, IEnumerable<DrawUserPair> visibleUsers, IEnumerable<DrawUserPair> onlineUsers, IEnumerable<DrawUserPair> pausedUsers, IEnumerable<DrawUserPair> offlineUsers)
|
||||
{
|
||||
if (_mareConfig.Current.ShowVisibleUsersSeparately)
|
||||
{
|
||||
using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, allUsers);
|
||||
using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
}
|
||||
|
||||
foreach (var tag in tagsWithPairsInThem)
|
||||
{
|
||||
if (_mareConfig.Current.ShowOfflineUsersSeparately)
|
||||
{
|
||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, onlineUsers, allUsers, visibleUsers);
|
||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, onlineUsers, pausedUsers, allUsers, visibleUsers);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, allUsers, allUsers, visibleUsers);
|
||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, allUsers, Enumerable.Empty<DrawUserPair>(), allUsers, visibleUsers);
|
||||
}
|
||||
}
|
||||
|
||||
if (_mareConfig.Current.ShowOfflineUsersSeparately)
|
||||
{
|
||||
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
|
||||
onlineUsers.Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), allUsers);
|
||||
onlineUsers.Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
if (pausedUsers.Any()) using (ImRaii.PushId("group-PausedCustomTag")) DrawCategory(TagHandler.CustomPausedTag,
|
||||
Enumerable.Empty<DrawUserPair>(), pausedUsers, allUsers);
|
||||
using (ImRaii.PushId($"group-OfflineCustomTag")) DrawCategory(TagHandler.CustomOfflineTag,
|
||||
offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired()).ToList(), allUsers);
|
||||
offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired()).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
|
||||
onlineUsers.Concat(offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired())).Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), allUsers);
|
||||
onlineUsers.Concat(offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired())).Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
}
|
||||
|
||||
using (ImRaii.PushId($"group-UnpairedCustomTag")) DrawCategory(TagHandler.CustomUnpairedTag,
|
||||
offlineUsers.Where(u => !u.UserPair!.OtherPermissions.IsPaired()).ToList(), allUsers);
|
||||
offlineUsers.Where(u => !u.UserPair!.OtherPermissions.IsPaired()).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
}
|
||||
|
||||
|
||||
private void PauseRemainingPairs(List<DrawUserPair> availablePairs)
|
||||
{
|
||||
foreach (var pairToPause in availablePairs.Where(pair => !pair.UserPair!.OwnPermissions.IsPaused()))
|
||||
|
@@ -203,10 +203,10 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
DtrStyle.Style4 => $"\xE03A {text}",
|
||||
DtrStyle.Style5 => $"\xE033 {text}",
|
||||
DtrStyle.Style6 => $"\xE038 {text}",
|
||||
DtrStyle.Style7 => $"\xE05D {text}",
|
||||
DtrStyle.Style7 => $"\xE044 {text}",
|
||||
DtrStyle.Style8 => $"\xE03C{text}",
|
||||
DtrStyle.Style9 => $"\xE040 {text} \xE041",
|
||||
_ => $"\uE044 {text}"
|
||||
_ => $"\uE05D {text}"
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@ using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.ImGuiFileDialog;
|
||||
using Dalamud.Interface.Textures.TextureWraps;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Utility;
|
||||
using MareSynchronos.API.Data;
|
||||
using MareSynchronos.API.Dto.User;
|
||||
using MareSynchronos.Services;
|
||||
@@ -28,14 +29,14 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
private IDalamudTextureWrap? _pfpTextureWrap;
|
||||
private string _profileDescription = string.Empty;
|
||||
private byte[] _profileImage = [];
|
||||
private bool _showFileDialogError = false;
|
||||
private string _showFileDialogError = string.Empty;
|
||||
private bool _wasOpen;
|
||||
|
||||
public EditProfileUi(ILogger<EditProfileUi> logger, MareMediator mediator,
|
||||
ApiController apiController, UiSharedService uiSharedService, FileDialogManager fileDialogManager,
|
||||
ServerConfigurationManager serverConfigurationManager,
|
||||
MareProfileManager mareProfileManager, PerformanceCollectorService performanceCollectorService)
|
||||
: base(logger, mediator, "Snowcloak Edit Profile###SnowcloakSyncEditProfileUI", performanceCollectorService)
|
||||
: base(logger, mediator, "Snowcloak Profile Editor###SnowcloakSyncEditProfileUI", performanceCollectorService)
|
||||
{
|
||||
IsOpen = false;
|
||||
this.SizeConstraints = new()
|
||||
@@ -92,20 +93,13 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
ImGui.Image(_pfpTextureWrap.Handle, ImGuiHelpers.ScaledVector2(_pfpTextureWrap.Width, _pfpTextureWrap.Height));
|
||||
}
|
||||
|
||||
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
||||
var spacing = ImGui.GetStyle().ItemSpacing.X + 200;
|
||||
ImGuiHelpers.ScaledRelativeSameLine(256, spacing);
|
||||
using (_uiSharedService.GameFont.Push())
|
||||
{
|
||||
var descriptionTextSize = ImGui.CalcTextSize(profile.Description, hideTextAfterDoubleHash: false, 256f);
|
||||
var childFrame = ImGuiHelpers.ScaledVector2(256 + ImGui.GetStyle().WindowPadding.X + ImGui.GetStyle().WindowBorderSize, 256);
|
||||
if (descriptionTextSize.Y > childFrame.Y)
|
||||
{
|
||||
_adjustedForScollBarsOnlineProfile = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_adjustedForScollBarsOnlineProfile = false;
|
||||
}
|
||||
_adjustedForScollBarsOnlineProfile = (descriptionTextSize.Y > childFrame.Y);
|
||||
childFrame = childFrame with
|
||||
{
|
||||
X = childFrame.X + (_adjustedForScollBarsOnlineProfile ? ImGui.GetStyle().ScrollbarSize : 0),
|
||||
@@ -122,9 +116,18 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
ImGui.Checkbox("Is NSFW", ref nsfw);
|
||||
ImGui.EndDisabled();
|
||||
|
||||
ImGui.Separator();
|
||||
_uiSharedService.BigText("Rules and Guidelines");
|
||||
UiSharedService.ColorTextWrapped("Users that are paired with you (not paused) will be able to see your profile picture and description.", ImGuiColors.DalamudWhite);
|
||||
UiSharedService.ColorTextWrapped("All users have the capability to report your profile if it violates the rules.", ImGuiColors.DalamudGrey);
|
||||
UiSharedService.ColorTextWrapped(" - Please do NOT upload anything that can be considered highly illegal or obscene (beastiality, sexual acts depicting minors or anything representing a minor (including Lalafel), etc.)", ImGuiColors.DalamudRed);
|
||||
UiSharedService.ColorTextWrapped(" - Please avoid the use of slurs, hate speech, threatening behaviour, etc.", ImGuiColors.DalamudRed);
|
||||
UiSharedService.ColorTextWrapped(" - In the event we receive a report of an offensive profile, we may disable your profile forever or terminate your Snowcloak service account.", ImGuiColors.DalamudRed);
|
||||
UiSharedService.ColorTextWrapped(" - You may not appeal any bans of your profile and or Snowcloak service account.", ImGuiColors.DalamudRed);
|
||||
UiSharedService.ColorTextWrapped("Users who wish to mark their profile as NSFW should enable the toggle below.", ImGuiColors.DalamudWhite);
|
||||
ImGui.Separator();
|
||||
_uiSharedService.BigText("Profile Settings");
|
||||
|
||||
UiSharedService.ColorTextWrapped("Profile pictures must be cropped to 256x256px and have a file size of 250KiB or smaller.", ImGuiColors.DalamudGrey);
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile picture"))
|
||||
{
|
||||
_fileDialogManager.OpenFileDialog("Select new Profile picture", ".png", (success, file) =>
|
||||
@@ -138,11 +141,10 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
|
||||
if (format.Width > 256 || format.Height > 256 || (fileContent.Length > 250 * 1024))
|
||||
{
|
||||
_showFileDialogError = true;
|
||||
_showFileDialogError = format.Width > 256 || format.Height > 256 ? "ERROR: Image dimensions must be 256x256px or smaller." : fileContent.Length > 250 * 1024 ? "ERROR: File size was bigger than 250KiB" : "ERROR: An unknown error has occured.";
|
||||
return;
|
||||
}
|
||||
|
||||
_showFileDialogError = false;
|
||||
_showFileDialogError = string.Empty;
|
||||
await _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, Convert.ToBase64String(fileContent), Description: null))
|
||||
.ConfigureAwait(false);
|
||||
});
|
||||
@@ -155,9 +157,9 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, "", Description: null));
|
||||
}
|
||||
UiSharedService.AttachToolTip("Clear your currently uploaded profile picture");
|
||||
if (_showFileDialogError)
|
||||
if (!_showFileDialogError.IsNullOrEmpty())
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("The profile picture must be a PNG file with a maximum height and width of 256px and 250KiB size", ImGuiColors.DalamudRed);
|
||||
UiSharedService.ColorTextWrapped(_showFileDialogError, ImGuiColors.DalamudRed);
|
||||
}
|
||||
var isNsfw = profile.IsNSFW;
|
||||
if (ImGui.Checkbox("Profile is NSFW", ref isNsfw))
|
||||
|
@@ -9,6 +9,7 @@ public class TagHandler
|
||||
public const string CustomOnlineTag = "Mare_Online";
|
||||
public const string CustomUnpairedTag = "Mare_Unpaired";
|
||||
public const string CustomVisibleTag = "Mare_Visible";
|
||||
public const string CustomPausedTag = "Mare_Paused";
|
||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||
|
||||
public TagHandler(ServerConfigurationManager serverConfigurationManager)
|
||||
|
@@ -106,9 +106,8 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
if (_uiShared.IsInGpose) return;
|
||||
|
||||
if ((!_configService.Current.AcceptedAgreement || _configService.Current.AcceptedTOSVersion != _configService.Current.ExpectedTOSVersion) && !_readFirstPage)
|
||||
if (!_configService.Current.AcceptedAgreement && !_readFirstPage)
|
||||
{
|
||||
// TODO: The UI bugs hard if this page *isn't* shown before the new TOS. There's probably a way around it.
|
||||
_uiShared.BigText("Welcome to Snowcloak");
|
||||
ImGui.Separator();
|
||||
UiSharedService.TextWrapped("Snowcloak is a plugin that will replicate your full current character state including all Penumbra mods to other paired users. " +
|
||||
@@ -126,7 +125,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
#if !DEBUG
|
||||
_timeoutTask = Task.Run(async () =>
|
||||
{
|
||||
for (int i = 45; i > 0; i--)
|
||||
for (int i = 10; i > 0; i--)
|
||||
{
|
||||
_timeoutLabel = $"'I agree' button will be available in {i}s";
|
||||
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
|
||||
@@ -137,7 +136,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if ((!_configService.Current.AcceptedAgreement || _configService.Current.AcceptedTOSVersion != _configService.Current.ExpectedTOSVersion) && _readFirstPage)
|
||||
else if (!_configService.Current.AcceptedAgreement && _readFirstPage)
|
||||
{
|
||||
using (_uiShared.UidFont.Push())
|
||||
{
|
||||
@@ -152,7 +151,6 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
UiSharedService.ColorText(readThis, ImGuiColors.DalamudRed);
|
||||
ImGui.SetWindowFontScale(1.0f);
|
||||
ImGui.Separator();
|
||||
|
||||
UiSharedService.TextWrapped("""
|
||||
To use Snowcloak, you must be over the age of 18, or 21 in some jurisdictions.
|
||||
""");
|
||||
@@ -190,7 +188,6 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
if (ImGui.Button("I agree##toSetup"))
|
||||
{
|
||||
_configService.Current.AcceptedAgreement = true;
|
||||
_configService.Current.AcceptedTOSVersion = _configService.Current.ExpectedTOSVersion;
|
||||
_configService.Save();
|
||||
}
|
||||
}
|
||||
@@ -199,7 +196,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
UiSharedService.TextWrapped(_timeoutLabel);
|
||||
}
|
||||
}
|
||||
else if ((!_configService.Current.AcceptedAgreement || _configService.Current.AcceptedTOSVersion != _configService.Current.ExpectedTOSVersion)
|
||||
else if (_configService.Current.AcceptedAgreement
|
||||
&& (string.IsNullOrEmpty(_configService.Current.CacheFolder)
|
||||
|| !_configService.Current.InitialScanComplete
|
||||
|| !Directory.Exists(_configService.Current.CacheFolder)))
|
||||
|
@@ -956,6 +956,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.BigText("UI");
|
||||
var showCharacterNames = _configService.Current.ShowCharacterNames;
|
||||
var showVisibleSeparate = _configService.Current.ShowVisibleUsersSeparately;
|
||||
var sortSyncshellByVRAM = _configService.Current.SortSyncshellsByVRAM;
|
||||
var showOfflineSeparate = _configService.Current.ShowOfflineUsersSeparately;
|
||||
var showProfiles = _configService.Current.ProfilesShow;
|
||||
var showNsfwProfiles = _configService.Current.ProfilesAllowNsfw;
|
||||
@@ -1074,13 +1075,20 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_configService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("This will show all currently visible users in a special 'Visible' group in the main UI.");
|
||||
if (ImGui.Checkbox("Sort visible syncshell users by VRAM usage", ref sortSyncshellByVRAM))
|
||||
{
|
||||
_configService.Current.SortSyncshellsByVRAM = sortSyncshellByVRAM;
|
||||
_logger.LogWarning("Changing value: {sortSyncshellsByVRAM}", sortSyncshellByVRAM);
|
||||
|
||||
if (ImGui.Checkbox("Show separate Offline group", ref showOfflineSeparate))
|
||||
_configService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("This will put users using the most VRAM in a syncshell at the top of the list.");
|
||||
if (ImGui.Checkbox("Group users by connection status", ref showOfflineSeparate))
|
||||
{
|
||||
_configService.Current.ShowOfflineUsersSeparately = showOfflineSeparate;
|
||||
_configService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("This will show all currently offline users in a special 'Offline' group in the main UI.");
|
||||
_uiShared.DrawHelpText("This will categorize users by their connection status in the main UI.");
|
||||
|
||||
if (ImGui.Checkbox("Show player names", ref showCharacterNames))
|
||||
{
|
||||
|
@@ -20,7 +20,7 @@ public class PngHdr
|
||||
|
||||
stream.ReadExactly(buffer[..8]);
|
||||
|
||||
uint ihdrLength = BitConverter.ToUInt32(buffer);
|
||||
uint ihdrLength = ReadBigEndianUInt32(buffer[..4]);
|
||||
|
||||
// The next four bytes will be the length of the IHDR section (it should be 13 bytes but we only need 8)
|
||||
if (ihdrLength < 8)
|
||||
@@ -32,8 +32,8 @@ public class PngHdr
|
||||
|
||||
stream.ReadExactly(buffer[..8]);
|
||||
|
||||
uint width = BitConverter.ToUInt32(buffer);
|
||||
uint height = BitConverter.ToUInt32(buffer[4..]);
|
||||
uint width = ReadBigEndianUInt32(buffer[..4]);
|
||||
uint height = ReadBigEndianUInt32(buffer[4..8]);
|
||||
|
||||
// Validate the width/height are non-negative and... that's all we care about!
|
||||
if (width > int.MaxValue || height > int.MaxValue)
|
||||
@@ -46,4 +46,12 @@ public class PngHdr
|
||||
return InvalidSize;
|
||||
}
|
||||
}
|
||||
// Minimal helper for big-endian conversion
|
||||
private static uint ReadBigEndianUInt32(ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
return ((uint)bytes[0] << 24) |
|
||||
((uint)bytes[1] << 16) |
|
||||
((uint)bytes[2] << 8) |
|
||||
bytes[3];
|
||||
}
|
||||
}
|
@@ -121,7 +121,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
{
|
||||
Logger.LogWarning("Multiple secret keys for current character");
|
||||
_connectionDto = null;
|
||||
Mediator.Publish(new NotificationMessage("Multiple Identical Characters detected", "Your Service configuration has multiple characters with the same name and world set up. Delete the duplicates in the character management to be able to connect to Mare.",
|
||||
Mediator.Publish(new NotificationMessage("Multiple Identical Characters detected", "Your Service configuration has multiple characters with the same name and world set up. Delete the duplicates in the character management to be able to connect.",
|
||||
NotificationType.Error));
|
||||
await StopConnection(ServerState.MultiChara).ConfigureAwait(false);
|
||||
_connectionCancellationTokenSource?.Cancel();
|
||||
@@ -183,6 +183,8 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
|
||||
_connectionDto = await GetConnectionDto().ConfigureAwait(false);
|
||||
|
||||
await CheckClientHealth().ConfigureAwait(false);
|
||||
|
||||
ServerState = ServerState.Connected;
|
||||
|
||||
var currentClientVer = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
@@ -314,8 +316,12 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
while (!ct.IsCancellationRequested && _mareHub != null)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(30), ct).ConfigureAwait(false);
|
||||
Logger.LogDebug("Checking Client Health State");
|
||||
_ = await CheckClientHealth().ConfigureAwait(false);
|
||||
var healthy = await CheckClientHealth().ConfigureAwait(false);
|
||||
if (!healthy || _mareHub.State != HubConnectionState.Connected)
|
||||
{
|
||||
Logger.LogWarning("Health check failed, forcing reconnect. ClientHealth: {0} HubConnected: {1}", healthy, _mareHub.State != HubConnectionState.Connected);
|
||||
await ForceResetConnection().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,7 +397,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
{
|
||||
var users = await GroupsGetUsersInGroup(group).ConfigureAwait(false);
|
||||
foreach (var user in users)
|
||||
{
|
||||
{
|
||||
Logger.LogDebug("Group Pair: {user}", user);
|
||||
_pairManager.AddGroupPair(user);
|
||||
}
|
||||
@@ -478,5 +484,30 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
|
||||
ServerState = state;
|
||||
}
|
||||
//Because this plugin really likes to bug out with connections, lets "fix" it....
|
||||
public async Task ForceResetConnection()
|
||||
{
|
||||
if (!_initialized) return;
|
||||
Logger.LogInformation("ForceReconnect called");
|
||||
|
||||
try
|
||||
{
|
||||
await StopConnection(ServerState.Disconnected).ConfigureAwait(false);
|
||||
|
||||
// Cancel any ongoing health checks to prevent conflicts
|
||||
_healthCheckTokenSource?.Cancel();
|
||||
_healthCheckTokenSource?.Dispose();
|
||||
_healthCheckTokenSource = null;
|
||||
|
||||
await CreateConnections().ConfigureAwait(false);
|
||||
|
||||
Logger.LogInformation("ForceReconnect completed successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Failure during ForceReconnect, disconnecting");
|
||||
await StopConnection(ServerState.Disconnected).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore MA0040
|
BIN
MareSynchronos/images/logo.png
Normal file
BIN
MareSynchronos/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
@@ -10,9 +10,9 @@
|
||||
},
|
||||
"DalamudPackager": {
|
||||
"type": "Direct",
|
||||
"requested": "[13.0.0, )",
|
||||
"resolved": "13.0.0",
|
||||
"contentHash": "Mb3cUDSK/vDPQ8gQIeuCw03EMYrej1B4J44a1AvIJ9C759p9XeqdU9Hg4WgOmlnlPe0G7ILTD32PKSUpkQNa8w=="
|
||||
"requested": "[13.1.0, )",
|
||||
"resolved": "13.1.0",
|
||||
"contentHash": "XdoNhJGyFby5M/sdcRhnc5xTop9PHy+H50PTWpzLhJugjB19EDBiHD/AsiDF66RETM+0qKUdJBZrNuebn7qswQ=="
|
||||
},
|
||||
"DotNet.ReproducibleBuilds": {
|
||||
"type": "Direct",
|
||||
@@ -22,11 +22,11 @@
|
||||
},
|
||||
"Downloader": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.3.4, )",
|
||||
"resolved": "3.3.4",
|
||||
"contentHash": "/M/c80e1L0WW1XrLSSiQhgFxk8rrfbpWiWDn2CeBg1tPD393Neo+v184yG/ThyhE9rrNp36yCrugiCmEbRf+VQ==",
|
||||
"requested": "[4.0.3, )",
|
||||
"resolved": "4.0.3",
|
||||
"contentHash": "Vg1+UqPDstpMw2CKXV9XvB8jKHC95KQfbqPxQXvOMRMFnTov4Ixvvw6GZV5DXLnKuL2sfnmVYX9CaQtcURia1Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "8.0.1"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "8.0.3"
|
||||
}
|
||||
},
|
||||
"Glamourer.Api": {
|
||||
@@ -55,11 +55,28 @@
|
||||
"System.IO.Pipelines": "6.0.3"
|
||||
}
|
||||
},
|
||||
"MessagePack": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.1.4, )",
|
||||
"resolved": "3.1.4",
|
||||
"contentHash": "BH0wlHWmVoZpbAPyyt2Awbq30C+ZsS3eHSkYdnyUAbqVJ22fAJDzn2xTieBeoT5QlcBzp61vHcv878YJGfi3mg==",
|
||||
"dependencies": {
|
||||
"MessagePack.Annotations": "3.1.4",
|
||||
"MessagePackAnalyzer": "3.1.4",
|
||||
"Microsoft.NET.StringTools": "17.11.4"
|
||||
}
|
||||
},
|
||||
"MessagePack.Annotations": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.1.4, )",
|
||||
"resolved": "3.1.4",
|
||||
"contentHash": "aVWrDAkCdqxwQsz/q0ldPh2EFn48M99YUzE9OvZjMq2RNLKz4o2z88iGFvSvbMqOWRweRvKPHBJZe22PRqzslQ=="
|
||||
},
|
||||
"Meziantou.Analyzer": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.0.212, )",
|
||||
"resolved": "2.0.212",
|
||||
"contentHash": "U91ktjjTRTccUs3Lk+hrLD9vW+2+lhnsOf4G1GpRSJi1pLn3uK5CU6wGP9Bmz1KlJs6Oz1GGoMhxQBoqQsmAuQ=="
|
||||
"requested": "[2.0.213, )",
|
||||
"resolved": "2.0.213",
|
||||
"contentHash": "LHnFGBqhlBjbf8Uo4OIzGM0llRxFrIMuo/hP9oHq+aldS+28G4LqG12LK0co9b+S0yj1Vbf0rclDHN0Ji2DTkA=="
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Client": {
|
||||
"type": "Direct",
|
||||
@@ -133,6 +150,12 @@
|
||||
"Microsoft.IdentityModel.Tokens": "8.14.0"
|
||||
}
|
||||
},
|
||||
"System.IO.Pipelines": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.8, )",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "6vPmJt73mgUo1gzc/OcXlJvClz/2jxZ4TQPRfriVaLoGRH2mye530D9WHJYbFQRNMxF3PWCoeofsFdCyN7fLzA=="
|
||||
},
|
||||
"K4os.Compression.LZ4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.3.8",
|
||||
@@ -143,19 +166,10 @@
|
||||
"resolved": "1.0.8",
|
||||
"contentHash": "Wp2F7BamQ2Q/7Hk834nV9vRQapgcr8kgv9Jvfm8J3D0IhDqZMMl+a2yxUq5ltJitvXvQfB8W6K4F4fCbw/P6YQ=="
|
||||
},
|
||||
"MessagePack": {
|
||||
"MessagePackAnalyzer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.5.187",
|
||||
"contentHash": "uW4j8m4Nc+2Mk5n6arOChavJ9bLjkis0qWASOj2h2OwmfINuzYv+mjCHUymrYhmyyKTu3N+ObtTXAY4uQ7jIhg==",
|
||||
"dependencies": {
|
||||
"MessagePack.Annotations": "2.5.187",
|
||||
"Microsoft.NET.StringTools": "17.6.3"
|
||||
}
|
||||
},
|
||||
"MessagePack.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.5.198",
|
||||
"contentHash": "3U9OvqQGTra+Mz1k1zfNAScSdNHobnqtQ51qdMGUZppkNDZJl0X/igq6Qz5zDBLEZoYqZrFtZwFx6wBJHHI8BA=="
|
||||
"resolved": "3.1.4",
|
||||
"contentHash": "CTaSsN/liJ7MhLCAB7Z4ZLBNuVGCq9lt2BT/cbrc9vzGv89yK3CqIA+z9T19a11eQYl9etZHL6MQJgCqECRVpg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": {
|
||||
"type": "Transitive",
|
||||
@@ -499,19 +513,14 @@
|
||||
},
|
||||
"Microsoft.NET.StringTools": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.6.3",
|
||||
"contentHash": "N0ZIanl1QCgvUumEL1laasU0a7sOE5ZwLZVTn0pAePnfhq8P7SvTjF8Axq+CnavuQkmdQpGNXQ1efZtu5kDFbA=="
|
||||
"resolved": "17.11.4",
|
||||
"contentHash": "mudqUHhNpeqIdJoUx2YDWZO/I9uEDYVowan89R6wsomfnUJQk6HteoQTlNjZDixhT2B4IXMkMtgZtoceIjLRmA=="
|
||||
},
|
||||
"System.Diagnostics.EventLog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "gebRF3JLLJ76jz1CQpvwezNapZUjFq20JQsaGHzBH0DzlkHBLpdhwkOei9usiOkIGMwU/L0ALWpNe1JE+5/itw=="
|
||||
},
|
||||
"System.IO.Pipelines": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.3",
|
||||
"contentHash": "ryTgF+iFkpGZY1vRQhfCzX0xTdlV3pyaTTqRu2ETbEv+HlV7O6y7hyQURnghNIXvctl5DuZ//Dpks6HdL/Txgw=="
|
||||
},
|
||||
"System.Net.ServerSentEvents": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
@@ -525,8 +534,11 @@
|
||||
"maresynchronos.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"MessagePack.Annotations": "[2.5.198, )"
|
||||
"MessagePack.Annotations": "[2.5.129, )"
|
||||
}
|
||||
},
|
||||
"snowcloaksync": {
|
||||
"type": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
9
SnowcloakSync/SnowcloakSync.csproj
Normal file
9
SnowcloakSync/SnowcloakSync.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
9
SnowcloakSync/Utils/Colours.cs
Normal file
9
SnowcloakSync/Utils/Colours.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace SnowcloakSync.Utils
|
||||
{
|
||||
public static class Colours
|
||||
{
|
||||
public static readonly Vector4 _snowcloakOnline = new(0.4275f, 0.6863f, 1f, 1f);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user