Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
36e1f38
[skip ci] Update README.md
neon-nyan May 10, 2026
1cd353a
Update EncTool usage
neon-nyan May 13, 2026
a29a5e0
Update NuGet
neon-nyan May 13, 2026
6f49d01
Make ThrottleServiceContext a reference struct
neon-nyan May 13, 2026
5e0bd95
Update Hi3Helper.EncTool
neon-nyan May 13, 2026
a266cc0
Fix COM Marshalling + Memory Leaks
neon-nyan May 14, 2026
11893ff
Fix canary build
neon-nyan May 14, 2026
defee89
Update static lib
neon-nyan May 14, 2026
28ef475
Moving to -O2 for AOT compilation
neon-nyan May 14, 2026
afee145
Update Hi3Helper.Win32
neon-nyan May 14, 2026
0e0f37f
Update StaticLib
neon-nyan May 14, 2026
e04d904
Update Program.cs
neon-nyan May 14, 2026
9e2fb08
Avoid Hi3Helper.Throttle.dll from getting deleted
neon-nyan May 14, 2026
2af63f6
Fix early release of Plugin's COM object
neon-nyan May 14, 2026
ba50086
Remove finalizer on custom controls
neon-nyan May 14, 2026
8fbf93b
Revert "Fix early release of Plugin's COM object"
neon-nyan May 14, 2026
81e26c1
Revert "Fix early release of Plugin's COM object"
neon-nyan May 14, 2026
3bd0796
Another fixes for COM Marshal
neon-nyan May 14, 2026
c39aae9
Fix early reload due to RegistryMonitor events
neon-nyan May 30, 2026
a265b2e
Use DefaultInterpolatedStringHandler on GetLaunchArguments
neon-nyan May 30, 2026
a406411
Update DiscordRPC submodule
neon-nyan May 30, 2026
b702061
Update NuGet and usages
neon-nyan May 30, 2026
2195b7d
Fix nullability (especially for GSP)
neon-nyan May 30, 2026
4ec6e8a
Sort Usings
neon-nyan May 30, 2026
bafd451
[Honkai GSP] Fix throw while saving empty game settings
neon-nyan May 30, 2026
bc855e7
Code QA
neon-nyan May 30, 2026
23fa83a
[HonkaiRepair] Fix Audio_Default redownload after game repair
neon-nyan May 30, 2026
79d4381
Fix CDN settings binding on Settings Page
neon-nyan May 30, 2026
2a962b4
Update Hi3Helper.SharpDiscordRPC
neon-nyan May 30, 2026
234445c
Fix MhyMurmurHash264B reporting wrong pre-defined length
neon-nyan May 30, 2026
6af9210
Fix MhyMurmurHash264B reporting wrong pre-defined length (pt. 2)
neon-nyan May 30, 2026
18f11bc
[BSDiff] Use SIMD on Diff Add (on 256 or 128 bit data)
neon-nyan May 30, 2026
76ad62a
[Hi3GameRepair] Fix 404 (Not Found) error for some present CGs
neon-nyan May 30, 2026
a503822
Update Hi3Helper.EncTool
neon-nyan May 30, 2026
fee7a73
Minor UI Adjustment
neon-nyan May 31, 2026
fef0162
Fix preload progress not updating to 100% on Sophon
neon-nyan May 31, 2026
4a32388
Use Storyboard on Carousel's Slideshow ticker
neon-nyan May 31, 2026
aa2beed
Fix multiple timer initialized while changing slide
neon-nyan May 31, 2026
347550d
Null check on _timerStoryboard
neon-nyan Jun 1, 2026
76b52ff
Remove unused usings
neon-nyan Jun 1, 2026
5dbebbc
[HSR 4.3] Adjustment on data struct (DesignDataV)
neon-nyan Jun 1, 2026
8b5cb1c
[HSR 4.3] Adjustment on data struct (IFixV)
neon-nyan Jun 1, 2026
5f569ff
Bump version
neon-nyan Jun 1, 2026
4c8478f
Update EncTool
neon-nyan Jun 1, 2026
787c272
[Hi3 Game Repair] Fix CN wrong VA files downloaded
neon-nyan Jun 1, 2026
374023e
Update NuGet
neon-nyan Jun 5, 2026
14e618e
Fix compile error
neon-nyan Jun 5, 2026
ec384e7
DiscordRPC code cleanup
neon-nyan Jun 6, 2026
c832666
Fix some UI thread block
neon-nyan Jun 6, 2026
58e18b8
Fix HomePage not initialized on Release builds
neon-nyan Jun 6, 2026
55a9403
Detach API loading logic to another thread
neon-nyan Jun 6, 2026
8873fc0
Update Hi3Helper.SharpDiscordRPC
neon-nyan Jun 6, 2026
1aba53d
Update ImageEx
neon-nyan Jun 6, 2026
5246b18
Allow video keep playing on transition before disposed
neon-nyan Jun 6, 2026
29a209d
Enable CDNCache by default on initial install
neon-nyan Jun 6, 2026
5041f17
Clean-up launcher settings
neon-nyan Jun 6, 2026
e8a4aa2
Fix nullability
neon-nyan Jun 6, 2026
8738231
Fix nullability (pt. 2)
neon-nyan Jun 6, 2026
26b3c47
Remove usings
neon-nyan Jun 6, 2026
a47415d
Adjust carousel background brush
neon-nyan Jun 6, 2026
4838fbe
Use design background size for event button
shatyuka Jun 6, 2026
d2118ab
Add hover image to event button
shatyuka Jun 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions CollapseLauncher/Classes/CachesManagement/Honkai/Fetch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using CollapseLauncher.RepairManagement;
using Hi3Helper;
using Hi3Helper.EncTool;
using Hi3Helper.EncTool.Enc;
using Hi3Helper.EncTool.Parser.KianaDispatch;
using Hi3Helper.UABT;
using System;
Expand Down Expand Up @@ -161,7 +162,7 @@ private IEnumerable<CacheAsset> EnumerateCacheTextAsset(CacheAssetType type, IEn
{
// Set isFirst flag as true if type is Data and
// also convert type as lowered string.
bool isFirst = type == CacheAssetType.Data;
bool isFirst = type == CacheAssetType.Data;
bool isNeedReadLuckyNumber = type == CacheAssetType.Data;

foreach (string line in enumerator)
Expand All @@ -178,9 +179,8 @@ private IEnumerable<CacheAsset> EnumerateCacheTextAsset(CacheAssetType type, IEn
}

// Get the lucky number if it does so 👀
if (isNeedReadLuckyNumber && int.TryParse(line, null, out int luckyNumber))
if (isNeedReadLuckyNumber && int.TryParse(line, null, out int _))
{
LuckyNumber = luckyNumber;
isNeedReadLuckyNumber = false;
continue;
}
Expand Down Expand Up @@ -297,7 +297,7 @@ await Parallel.ForEachAsync(EnumerateCacheTextAsset(type, dataTextAsset.GetStrin
return (count, size);
}

private byte[] GetAssetIndexSalt(string data)
private static byte[] GetAssetIndexSalt(string data)
{
// Get the salt from the string and return as byte[]
byte[] key;
Expand All @@ -314,8 +314,15 @@ private byte[] GetAssetIndexSalt(string data)
key = MetadataHelper.CurrentMasterKey?.Key;
}

MhyEncTool saltTool = new(data, key);
return saltTool.GetSalt();
byte[] saltBytes = new byte[8];
if (!MhyEncTool.TryGetSalt(data,
key,
saltBytes,
out _,
out Exception exception))
throw exception;

return saltBytes;
}

private string GetAssetBasePathByType(CacheAssetType type) => Path.Combine(GamePath!, type == CacheAssetType.Data ? "Data" : "Resources");
Expand All @@ -328,7 +335,5 @@ private static bool IsValidRegionFile(string input, string lang)
input.Contains($"{CacheRegionalCheckName}_{lang}");
// If none, then pass it as true (non-regional string)
}

public KianaDispatch GetCurrentGateway() => GameGateway;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using CollapseLauncher.Helper.Update;
using CollapseLauncher.Plugins;
using DiscordRPC;
using DiscordRPC.Entities;
using DiscordRPC.Message;
using Hi3Helper;
using System;
Expand Down Expand Up @@ -139,9 +140,9 @@ private void EnablePresence(ulong applicationId)
Logger.LogWriteLine("Discord Presence is Enabled!");
}

private void OnReady(object? _, ReadyMessage msg)
private void OnReady(object? sender, ReadyMessage? msg)
{
Logger.LogWriteLine($"Connected to Discord with user {msg.User.Username}");
Logger.LogWriteLine($"Connected to Discord with user {msg?.User?.Username}");
if (!_firstTimeConnect)
{
// Restart Discord RPC client
Expand All @@ -161,9 +162,9 @@ private void OnReady(object? _, ReadyMessage msg)
}
}

private static void OnPresenceUpdate(object? _, PresenceMessage msg)
private static void OnPresenceUpdate(object? sender, PresenceMessage? msg)
{
if (msg.Presence == null)
if (msg?.Presence == null)
{
Logger.LogWriteLine("Activity cleared!");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@
using CollapseLauncher.Plugins;
using Hi3Helper;
using Hi3Helper.Data;
using Hi3Helper.Shared.Region;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;

// ReSharper disable StringLiteralTypo
Expand Down
14 changes: 5 additions & 9 deletions CollapseLauncher/Classes/Extension/TaskExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,19 +205,15 @@ internal static async Task InitPluginComAsync<T>(this T initializableInterface,
throw new COMException($"Initialization for {nameof(T)} has failed with return code: {returnCode}", initTask.Exception);
}

// ReSharper disable once InconsistentNaming
private static readonly Guid IInitializableIid = new(ComInterfaceId.ExInitializable);
private static IInitializableTask GetInitializableTask<T>(T instance)
where T : class
{
if (!ComMarshal<T>.TryCastComObjectAs(instance,
in IInitializableIid,
out IInitializableTask? initTask,
out Exception? ex))
{
throw ex;
}

return initTask;
return !ComMarshal<T>.TryCastComObjectAs(instance,
in IInitializableIid,
out IInitializableTask? initTask,
out Exception? ex) ? throw ex : initTask;
}

internal static async Task GetResultFromAction<T>(this Task<T> task, Action<T> getResultAction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,31 @@ public static partial class UIElementExtensions
/// <param name="element">The <seealso cref="UIElement"/> member of an element</param>
/// <param name="inputCursor">The cursor you want to set. Use <see cref="InputSystemCursor.Create"/> to choose the cursor you want to set.</param>
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_ProtectedCursor")]
internal static extern void SetCursor(this UIElement element, InputCursor inputCursor);
private static extern void SetCursorInner(this UIElement element, InputCursor inputCursor);

/// <summary>
/// Set the cursor for the element.
/// </summary>
/// <param name="element">The <seealso cref="UIElement"/> member of an element</param>
/// <param name="inputCursor">The cursor you want to set. Use <see cref="InputSystemCursor.Create"/> to choose the cursor you want to set.</param>
internal static T SetCursor<T>(this T element, InputCursor inputCursor)
where T : UIElement
{
element.SetCursorInner(inputCursor);
return element;
}

/// <summary>
/// Set the cursor for the element.
/// </summary>
/// <param name="element">The <seealso cref="UIElement"/> member of an element</param>
/// <param name="inputCursor">The cursor you want to set. Use <see cref="InputSystemCursor.Create"/> to choose the cursor you want to set.</param>
internal static T SetCursor<T>(this T element, InputSystemCursorShape inputCursor)
where T : UIElement
{
element.SetCursorInner(InputSystemCursor.Create(inputCursor));
return element;
}

/// <summary>
/// Set the cursor for the element.
Expand All @@ -28,6 +52,17 @@ internal static T WithCursor<T>(this T element, InputCursor inputCursor) where T
return element;
}

/// <summary>
/// Set the cursor for the element.
/// </summary>
/// <param name="element">The <seealso cref="UIElement"/> member of an element</param>
/// <param name="inputCursor">The cursor you want to set. Use <see cref="InputSystemCursor.Create"/> to choose the cursor you want to set.</param>
internal static T WithCursor<T>(this T element, InputSystemCursorShape inputCursor) where T : UIElement
{
element.SetCursor(inputCursor);
return element;
}

[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_disposedFlags")]
private static extern ref int GetObjectReferenceDisposeFlags(this IObjectReference obj);

Expand Down
12 changes: 3 additions & 9 deletions CollapseLauncher/Classes/Extension/VelopackLocatorExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
using Hi3Helper.SentryHelper;
using Hi3Helper.Shared.Region;
using Hi3Helper.Win32.ShellLinkCOM;
using NuGet.Versioning;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
Expand All @@ -34,12 +32,8 @@ internal static void StartUpdaterHook(string aumid)
// its custom AUMID
IVelopackLogger? logger = ILoggerHelper.GetILogger("Velopack").ToVelopackLogger();

Process currentProcess = Process.GetCurrentProcess();

WindowsVelopackLocator locator =
new(currentProcess.MainModule!.FileName,
(uint)currentProcess.Id,
logger);
DefaultProcessImpl procDefault = new(logger);
WindowsVelopackLocator locator = new(procDefault, logger);
// HACK: Always ensure to set the AUMID field null so it won't
// set the AUMID to its own.
locator.GetLocatorAumidField() = null;
Expand Down Expand Up @@ -168,7 +162,7 @@ public static void TryCleanupFallbackUpdate(SemanticVersion newVersion)

// Try open the shortcut and check whether this shortcut is actually pointing to
// CollapseLauncher.exe file
using ShellLink shellLink = new(thisUserStartMenuShortcut);
ShellLink shellLink = new(thisUserStartMenuShortcut);
// Try to get the target path and its filename
string shortcutTargetPath = shellLink.Target;
if (!shortcutTargetPath.Equals(currentExecutedPath, StringComparison.OrdinalIgnoreCase))
Expand Down
37 changes: 17 additions & 20 deletions CollapseLauncher/Classes/Extension/WriteableBitmapExtension.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Hi3Helper;
using Hi3Helper.SentryHelper;
using Hi3Helper.Win32.ManagedTools;
using Hi3Helper.Win32.Native.Interfaces;
using Hi3Helper.Win32.WinRT.IBufferCOM;
using Microsoft.UI.Xaml.Media.Imaging;
Expand All @@ -9,29 +8,27 @@
#pragma warning disable IDE0130

#nullable enable
namespace CollapseLauncher.Extension
namespace CollapseLauncher.Extension;

internal static class WriteableBitmapExtension
{
internal static class WriteableBitmapExtension
internal static nint GetBufferPointer(this WriteableBitmap writeableBitmap, out uint length)
{
internal static nint GetBufferPointer(this WriteableBitmap writeableBitmap, out uint length)
length = writeableBitmap.PixelBuffer.Length;
try
{
length = writeableBitmap.PixelBuffer.Length;
IBufferByteAccess byteAccess = writeableBitmap.PixelBuffer.AsBufferByteAccess();
try
{
byteAccess.Buffer(out nint bufferP);
return bufferP;
}
finally
{
if (!ComMarshal<IBufferByteAccess>.TryReleaseComObject(byteAccess, out Exception? ex))
{
SentryHelper.ExceptionHandler(ex, SentryHelper.ExceptionType.UnhandledOther);
Logger.LogWriteLine($"Cannot free the instance of IBufferByteAccess from WriteableBitmap\r\n{ex}",
LogType.Error,
true);
}
}
byteAccess.Buffer(out nint bufferP);
return bufferP;
}
catch (Exception ex)
{
SentryHelper.ExceptionHandler(ex, SentryHelper.ExceptionType.UnhandledOther);
Logger.LogWriteLine($"Cannot free the instance of IBufferByteAccess from WriteableBitmap\r\n{ex}",
LogType.Error,
true);
}

return nint.Zero;
}
}
2 changes: 1 addition & 1 deletion CollapseLauncher/Classes/FileDialog/FileDialogHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal static class FileDialogHelper
/// <param name="title">The title of the folder dialog</param>
/// <param name="checkOverride">Override path check and returns the actual string</param>
/// <returns>If <seealso cref="string"/> is empty, then it's cancelled. Otherwise, returns a selected path</returns>
internal static async Task<string> GetRestrictedFolderPathDialog(string? title = null, Func<string, Task<string>>? checkOverride = null)
internal static async Task<string> GetRestrictedFolderPathDialog(string? title = null, Func<string, Task<string?>>? checkOverride = null)
{
StartGet:
string dirPath = await FileDialogNative.GetFolderPicker(title);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,18 @@ private async Task<string> StartRoutineInner(FileMigrationProcessUIRef uiRef)

private async Task<string> MoveFile(FileMigrationProcessUIRef uiRef)
{
FileInfo inputPathInfo = new FileInfo(InputPath);
FileInfo outputPathInfo = new FileInfo(OutputPath);
FileInfo inputPathInfo = new(InputPath);
FileInfo outputPathInfo = new(OutputPath);

var inputPathDir = FileDialogHelper.IsRootPath(InputPath)
string inputPathDir = FileDialogHelper.IsRootPath(InputPath)
? Path.GetPathRoot(InputPath)
: Path.GetDirectoryName(inputPathInfo.FullName);

if (string.IsNullOrEmpty(inputPathDir))
throw new InvalidOperationException(string.Format(Locale.Current.Lang?._Dialogs?.InvalidGameDirNewTitleFormat,
throw new InvalidOperationException(string.Format(Locale.Current.Lang?._Dialogs?.InvalidGameDirNewTitleFormat ?? "",
InputPath));

DirectoryInfo outputPathDirInfo = new DirectoryInfo(inputPathDir);
DirectoryInfo outputPathDirInfo = new(inputPathDir);
outputPathDirInfo.Create();

// Update path display
Expand All @@ -129,8 +129,8 @@ private async Task<string> MoveFile(FileMigrationProcessUIRef uiRef)

private async Task<string> MoveDirectory(FileMigrationProcessUIRef uiRef)
{
DirectoryInfo inputPathInfo = new DirectoryInfo(InputPath);
DirectoryInfo outputPathInfo = new DirectoryInfo(OutputPath);
DirectoryInfo inputPathInfo = new(InputPath);
DirectoryInfo outputPathInfo = new(OutputPath);
outputPathInfo.Create();

bool isMoveBackward = inputPathInfo.FullName.StartsWith(outputPathInfo.FullName, StringComparison.OrdinalIgnoreCase) &&
Expand All @@ -148,7 +148,7 @@ private async Task<string> MoveDirectory(FileMigrationProcessUIRef uiRef)
// reduce massive seeking, hence improving speed.
bool isBothSsd = DriveTypeChecker.IsDriveSsd(InputPath) &&
DriveTypeChecker.IsDriveSsd(OutputPath);
ParallelOptions parallelOptions = new ParallelOptions
ParallelOptions parallelOptions = new()
{
CancellationToken = TokenSource?.Token ?? CancellationToken.None,
MaxDegreeOfParallelism = isBothSsd ? LauncherConfig.AppCurrentThread : 1
Expand Down Expand Up @@ -238,7 +238,7 @@ async ValueTask Impl(FileInfo inputFileInfo, CancellationToken cancellationToken
else
{
Logger.LogWriteLine($"[FileMigrationProcess::MoveDirectory()] Moving directory content across different drives from: {inputFileInfo.FullName} to {outputNewFilePath}", LogType.Default, true);
FileInfo outputFileInfo = new FileInfo(outputNewFilePath);
FileInfo outputFileInfo = new(outputNewFilePath);
await MoveWriteFile(uiRef, inputFileInfo, outputFileInfo, cancellationToken);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ namespace CollapseLauncher.GameSettings;

internal class DummyGameSettings : SettingsBase
{
public DummyGameSettings()
{

}

public override string GetLaunchArguments(GamePresetProperty property)
{
StringBuilder parameter = new(1024);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Drawing;
using System.Text;
// ReSharper disable IdentifierTypo
// ReSharper disable GrammarMistakeInComment
// ReSharper disable StringLiteralTypo

namespace CollapseLauncher.GameSettings.Genshin
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public static ScreenSettingData Load(IGameSettings gameSettings)
$"{ex}", ex));
}

return new ScreenSettingData();
return new ScreenSettingData(gameSettings);
}

public override void Save()
Expand Down
Loading
Loading