19 Commits

Author SHA1 Message Date
abea8f0856 Fix PNG images being limited to 255px
Some checks failed
.NET Build and Publish to Gitea / build (pull_request) Has been cancelled
2025-08-31 14:13:16 -04:00
1624a84cf1 merge upstream 2025-08-31 06:47:27 +00:00
ba852831aa Update build.yml 2025-08-31 02:31:18 -04:00
5de9ad3a54 Update build.yml 2025-08-31 02:27:15 -04:00
4c8ce23e8a Update build.yml 2025-08-31 02:22:22 -04:00
2be5f5d320 MAYBE NOW IT WORKS? 2025-08-31 02:19:45 -04:00
c428f306ca NOW fix build issues??? 2025-08-31 02:07:22 -04:00
3dde713c91 Fix build issues? 2025-08-31 01:58:27 -04:00
3280446c7e Create build.yml 2025-08-31 01:35:49 -04:00
a408e22a68 Tentative Moodles v3 support. They might change something between now and release.
Some checks failed
.NET Build / build (push) Has been cancelled
2025-08-31 06:33:56 +01:00
1b71cda403 Version bump
Some checks failed
.NET Build / build (push) Has been cancelled
Create Release / build (push) Has been cancelled
2025-08-31 05:35:52 +01:00
eb8dbbd7f9 Petnames IPC update 2025-08-31 05:35:30 +01:00
abc361faf0 Hello!
Testing from the gitea instance owned by ProfessorFartsalot~
2025-08-31 00:01:07 -04:00
d5d3eef5f8 Version bump
Some checks failed
.NET Build / build (push) Has been cancelled
Create Release / build (push) Has been cancelled
2025-08-29 23:16:56 +01:00
9f553e57d2 Take Two, I love computers 2025-08-29 23:14:35 +01:00
35af19f82e TOS fixes. 2025-08-29 23:02:35 +01:00
c113868b58 Revert TOS patch
Some checks are pending
Create Release / build (push) Waiting to run
2025-08-29 23:00:38 +01:00
51c76e1b2a Merge remote-tracking branch 'origin/main' 2025-08-29 22:59:33 +01:00
c58f66ff4a Reversion due to bug 2025-08-29 22:57:53 +01:00
8 changed files with 79 additions and 22 deletions

View File

@@ -0,0 +1,52 @@
name: .NET Build and Publish to Gitea
on:
push:
branches: '*'
pull_request:
jobs:
build:
runs-on: self-hosted
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://imbuilding.anuke.org/api/v1/repos/ProfessorFartsalot/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"

View File

@@ -27,9 +27,9 @@ public sealed class IpcCallerMoodles : IIpcCaller
_moodlesApiVersion = pi.GetIpcSubscriber<int>("Moodles.Version"); _moodlesApiVersion = pi.GetIpcSubscriber<int>("Moodles.Version");
_moodlesOnChange = pi.GetIpcSubscriber<IPlayerCharacter, object>("Moodles.StatusManagerModified"); _moodlesOnChange = pi.GetIpcSubscriber<IPlayerCharacter, object>("Moodles.StatusManagerModified");
_moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtr"); _moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtrV2");
_moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtr"); _moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtrV2");
_moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtr"); _moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtrV2");
_moodlesOnChange.Subscribe(OnMoodlesChange); _moodlesOnChange.Subscribe(OnMoodlesChange);
@@ -47,7 +47,7 @@ public sealed class IpcCallerMoodles : IIpcCaller
{ {
try try
{ {
APIAvailable = _moodlesApiVersion.InvokeFunc() == 1; APIAvailable = _moodlesApiVersion.InvokeFunc() == 3;
} }
catch catch
{ {

View File

@@ -30,12 +30,12 @@ public sealed class IpcCallerPetNames : IIpcCaller
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
_mareMediator = mareMediator; _mareMediator = mareMediator;
_petnamesReady = pi.GetIpcSubscriber<object>("PetRenamer.Ready"); _petnamesReady = pi.GetIpcSubscriber<object>("PetRenamer.OnReady");
_petnamesDisposing = pi.GetIpcSubscriber<object>("PetRenamer.Disposing"); _petnamesDisposing = pi.GetIpcSubscriber<object>("PetRenamer.OnDisposing");
_apiVersion = pi.GetIpcSubscriber<(uint, uint)>("PetRenamer.ApiVersion"); _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"); _getPlayerData = pi.GetIpcSubscriber<string>("PetRenamer.GetPlayerData");
_setPlayerData = pi.GetIpcSubscriber<string, object>("PetRenamer.SetPlayerData"); _setPlayerData = pi.GetIpcSubscriber<string, object>("PetRenamer.SetPlayerData");
_clearPlayerData = pi.GetIpcSubscriber<ushort, object>("PetRenamer.ClearPlayerData"); _clearPlayerData = pi.GetIpcSubscriber<ushort, object>("PetRenamer.ClearPlayerData");
@@ -56,7 +56,7 @@ public sealed class IpcCallerPetNames : IIpcCaller
APIAvailable = _enabled?.InvokeFunc() ?? false; APIAvailable = _enabled?.InvokeFunc() ?? false;
if (APIAvailable) if (APIAvailable)
{ {
APIAvailable = _apiVersion?.InvokeFunc() is { Item1: 3, Item2: >= 1 }; APIAvailable = _apiVersion?.InvokeFunc() is { Item1: 4, Item2: >= 0 };
} }
} }
catch catch

View File

@@ -8,6 +8,6 @@ public static class ConfigurationExtensions
{ {
return configuration.AcceptedAgreement && configuration.InitialScanComplete return configuration.AcceptedAgreement && configuration.InitialScanComplete
&& !string.IsNullOrEmpty(configuration.CacheFolder) && !string.IsNullOrEmpty(configuration.CacheFolder)
&& Directory.Exists(configuration.CacheFolder) && configuration.AcceptedTOSVersion == configuration.ExpectedTOSVersion; && Directory.Exists(configuration.CacheFolder);
} }
} }

View File

@@ -2,7 +2,7 @@
<Project Sdk="Dalamud.NET.Sdk/13.0.0"> <Project Sdk="Dalamud.NET.Sdk/13.0.0">
<PropertyGroup> <PropertyGroup>
<AssemblyName>Snowcloak</AssemblyName> <AssemblyName>Snowcloak</AssemblyName>
<Version>0.2.0</Version> <Version>0.2.0.3</Version>
<PackageProjectUrl>https://github.com/Eauldane/SnowcloakClient/</PackageProjectUrl> <PackageProjectUrl>https://github.com/Eauldane/SnowcloakClient/</PackageProjectUrl>
</PropertyGroup> </PropertyGroup>

View File

@@ -106,9 +106,8 @@ public partial class IntroUi : WindowMediatorSubscriberBase
{ {
if (_uiShared.IsInGpose) return; 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"); _uiShared.BigText("Welcome to Snowcloak");
ImGui.Separator(); ImGui.Separator();
UiSharedService.TextWrapped("Snowcloak is a plugin that will replicate your full current character state including all Penumbra mods to other paired users. " + 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 #if !DEBUG
_timeoutTask = Task.Run(async () => _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"; _timeoutLabel = $"'I agree' button will be available in {i}s";
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
@@ -137,7 +136,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
#endif #endif
} }
} }
else if ((!_configService.Current.AcceptedAgreement || _configService.Current.AcceptedTOSVersion != _configService.Current.ExpectedTOSVersion) && _readFirstPage) else if (!_configService.Current.AcceptedAgreement && _readFirstPage)
{ {
using (_uiShared.UidFont.Push()) using (_uiShared.UidFont.Push())
{ {
@@ -152,7 +151,6 @@ public partial class IntroUi : WindowMediatorSubscriberBase
UiSharedService.ColorText(readThis, ImGuiColors.DalamudRed); UiSharedService.ColorText(readThis, ImGuiColors.DalamudRed);
ImGui.SetWindowFontScale(1.0f); ImGui.SetWindowFontScale(1.0f);
ImGui.Separator(); ImGui.Separator();
UiSharedService.TextWrapped(""" UiSharedService.TextWrapped("""
To use Snowcloak, you must be over the age of 18, or 21 in some jurisdictions. 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")) if (ImGui.Button("I agree##toSetup"))
{ {
_configService.Current.AcceptedAgreement = true; _configService.Current.AcceptedAgreement = true;
_configService.Current.AcceptedTOSVersion = _configService.Current.ExpectedTOSVersion;
_configService.Save(); _configService.Save();
} }
} }
@@ -199,7 +196,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
UiSharedService.TextWrapped(_timeoutLabel); UiSharedService.TextWrapped(_timeoutLabel);
} }
} }
else if ((!_configService.Current.AcceptedAgreement || _configService.Current.AcceptedTOSVersion != _configService.Current.ExpectedTOSVersion) else if (_configService.Current.AcceptedAgreement
&& (string.IsNullOrEmpty(_configService.Current.CacheFolder) && (string.IsNullOrEmpty(_configService.Current.CacheFolder)
|| !_configService.Current.InitialScanComplete || !_configService.Current.InitialScanComplete
|| !Directory.Exists(_configService.Current.CacheFolder))) || !Directory.Exists(_configService.Current.CacheFolder)))

View File

@@ -20,7 +20,7 @@ public class PngHdr
stream.ReadExactly(buffer[..8]); 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) // 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) if (ihdrLength < 8)
@@ -32,8 +32,8 @@ public class PngHdr
stream.ReadExactly(buffer[..8]); stream.ReadExactly(buffer[..8]);
uint width = BitConverter.ToUInt32(buffer); uint width = ReadBigEndianUInt32(buffer[..4]);
uint height = BitConverter.ToUInt32(buffer[4..]); uint height = ReadBigEndianUInt32(buffer[4..8]);
// Validate the width/height are non-negative and... that's all we care about! // Validate the width/height are non-negative and... that's all we care about!
if (width > int.MaxValue || height > int.MaxValue) if (width > int.MaxValue || height > int.MaxValue)
@@ -46,4 +46,12 @@ public class PngHdr
return InvalidSize; 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];
}
}

0
Test.txt Normal file
View File