Skip to content

Commit 727914e

Browse files
authored
Stable 1.83.16 Hotfix (#869)
![UpdateIsAvailable-Campaign](https://github.com/user-attachments/assets/5c5df62c-8570-4018-b6e7-66d5decf8278) # What's changed? - 1.83.16 - **[Fix]** Deleted assets still getting downloaded while updating Honkai: Star Rail and Zenless Zone Zero, by @neon-nyan This caused by the filtering of the asset is still being redirected to FilterSophonPatchAssetList, which is unused rather than to FilterAssetList. This causes the supposedly deleted assets to get included, causing files to be redownloaded if not exist. - **[Fix]** Fix Honkai Impact 3rd cutscene detection on Game Repair, by @neon-nyan **Full Changelog**: CL-v1.83.15...CL-v1.83.16 # Code Signing Policy > Free code signing provided by [SignPath.io], certificate by [SignPath Foundation] - This program will not transfer any information to other networked systems. - Read our full [**Privacy Policy**](https://github.com/CollapseLauncher/Collapse/blob/main/PRIVACY.md) - Also read our [**Third Party Notices**](https://github.com/CollapseLauncher/Collapse/blob/main/THIRD_PARTY_NOTICES.md) for license used by third party libraries that we use. [SignPath Foundation]:https://signpath.org [SignPath.io]:https://signpath.io
2 parents 45b516f + 9cce3af commit 727914e

31 files changed

Lines changed: 596 additions & 523 deletions

.github/workflows/dd-static-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ jobs:
1414

1515
- name: Check code meets quality and security standards
1616
id: datadog-static-analysis
17-
uses: DataDog/datadog-static-analyzer-github-action@v1
17+
uses: DataDog/datadog-static-analyzer-github-action@v3
1818
with:
1919
dd_api_key: ${{ secrets.DD_API_KEY }}
2020
dd_app_key: ${{ secrets.DD_APP_KEY }}
2121
dd_site: ap1.datadoghq.com
2222
secrets_enabled: false
2323
static_analysis_enabled: true
24-
cpu_count: 2
24+
cpu_count: 2

CollapseLauncher/Classes/CachesManagement/Honkai/Check.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,6 @@ private async Task<List<CacheAsset>> Check(List<CacheAsset> assetIndex, Cancella
5858
return returnAsset;
5959
}
6060

61-
private readonly SearchValues<string> _unusedSearchValues = SearchValues.Create([
62-
"output_log",
63-
"Crashes",
64-
"Verify.txt",
65-
"APM",
66-
"FBData",
67-
"asb.dat"
68-
], StringComparison.OrdinalIgnoreCase);
69-
7061
private void CheckUnusedAssets(List<CacheAsset> assetIndex, List<CacheAsset> returnAsset)
7162
{
7263
// Directory info and if the directory doesn't exist, return
@@ -76,13 +67,25 @@ private void CheckUnusedAssets(List<CacheAsset> assetIndex, List<CacheAsset> ret
7667
return;
7768
}
7869

70+
SearchValues<string> unusedSearchValues = SearchValues
71+
.Create(GameVersionManager.GamePreset.GameInstallFileInfo?.CacheUpdateUnusedFilesIgnoreList
72+
?? [
73+
"output_log",
74+
"Crashes",
75+
"Verify.txt",
76+
"APM",
77+
"FBData",
78+
"asb.dat",
79+
"MiHoYoSDK.log"
80+
], StringComparison.OrdinalIgnoreCase);
81+
7982
// Iterate the file contained in the _gamePath
8083
foreach (FileInfo fileInfo in directoryInfo.EnumerateFiles("*", SearchOption.AllDirectories)
8184
.EnumerateNoReadOnly())
8285
{
8386
ReadOnlySpan<char> filePath = fileInfo.FullName;
8487

85-
if (filePath.ContainsAny(_unusedSearchValues)
88+
if (filePath.ContainsAny(unusedSearchValues)
8689
|| assetIndex.Exists(x => x.ConcatPath == fileInfo.FullName))
8790
{
8891
continue;

CollapseLauncher/Classes/Helper/Metadata/PresetConfig.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ public enum LauncherType
8181

8282
public class GameInstallFileInfo
8383
{
84-
public string GameDataFolderName { get; init; } = string.Empty;
85-
public string[] FilesToDelete { get; init; } = [];
86-
public string[] FoldersToDelete { get; init; } = [];
87-
public string[] FoldersToKeepInData { get; init; } = [];
88-
public string[] FilesCleanupIgnoreList { get; init; } = [];
84+
public string GameDataFolderName { get; init; } = string.Empty;
85+
public string[] FilesToDelete { get; init; } = [];
86+
public string[] FoldersToDelete { get; init; } = [];
87+
public string[] FoldersToKeepInData { get; init; } = [];
88+
public string[] FilesCleanupIgnoreList { get; init; } = [];
89+
public string[] CacheUpdateUnusedFilesIgnoreList { get; init; } = [];
8990
}
9091

9192
public class SophonChunkUrls

CollapseLauncher/Classes/Helper/StreamUtility/StreamExtension.cs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -309,28 +309,42 @@ public static FileInfo ResolveSymlink(this FileInfo fileInfo)
309309
/// </summary>
310310
/// <param name="dir">The directory to remove.</param>
311311
/// <param name="recursive">Whether to remove all possibly empty directories recursively.</param>
312-
public static void DeleteEmptyDirectory(this string dir, bool recursive = false)
312+
public static bool DeleteEmptyDirectory(this string dir, bool recursive = false)
313313
=> new DirectoryInfo(dir).DeleteEmptyDirectory(recursive);
314314

315315
/// <summary>
316316
/// Deletes the directory if it is empty.
317317
/// </summary>
318318
/// <param name="dir">The directory to remove.</param>
319319
/// <param name="recursive">Whether to remove all possibly empty directories recursively.</param>
320-
public static void DeleteEmptyDirectory(this DirectoryInfo dir, bool recursive = false)
320+
public static bool DeleteEmptyDirectory(this DirectoryInfo dir, bool recursive = false)
321321
{
322-
if (recursive)
322+
try
323323
{
324-
foreach (DirectoryInfo childDir in dir.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
324+
if (!dir.Exists)
325325
{
326-
childDir.DeleteEmptyDirectory();
326+
return true;
327+
}
328+
329+
if (recursive)
330+
{
331+
foreach (DirectoryInfo childDir in dir.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
332+
{
333+
childDir.DeleteEmptyDirectory();
334+
}
327335
}
328-
}
329336

330-
FindFiles.TryIsDirectoryEmpty(dir.FullName, out bool isEmpty);
331-
if (isEmpty)
337+
FindFiles.TryIsDirectoryEmpty(dir.FullName, out bool isEmpty);
338+
if (isEmpty)
339+
{
340+
dir.Delete(true);
341+
}
342+
343+
return true;
344+
}
345+
catch
332346
{
333-
dir.Delete(true);
347+
return false;
334348
}
335349
}
336350

CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.Sophon.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ await TryGetAdditionalPackageForSophonDiff(httpClient,
796796
}
797797

798798
// Filter asset list
799-
await FilterSophonPatchAssetList(sophonUpdateAssetList, Token!.Token);
799+
await FilterAssetList(sophonUpdateAssetList, x => x.AssetName, Token!.Token);
800800

801801
// Get the remote chunk size
802802
ProgressPerFileSizeTotal = sophonUpdateAssetList.GetCalculatedDiffSize(!isPreloadMode);
@@ -925,12 +925,6 @@ await Parallel.ForEachAsync(sophonUpdateAssetList
925925
}
926926
}
927927

928-
protected virtual Task FilterSophonPatchAssetList(List<SophonAsset> itemList, CancellationToken token)
929-
{
930-
// NOP
931-
return Task.CompletedTask;
932-
}
933-
934928
private ValueTask RunSophonAssetDownloadThread(HttpClient client,
935929
SophonAsset asset,
936930
ParallelOptions parallelOptions)

CollapseLauncher/Classes/InstallManagement/StarRail/StarRailInstall.SophonPatch.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Hi3Helper.Data;
1+
using Hi3Helper;
2+
using Hi3Helper.Data;
23
using System;
34
using System.Buffers;
45
using System.Collections.Generic;
@@ -56,15 +57,19 @@ public override async Task FilterAssetList<T>(
5657
List<T> listFiltered = [];
5758
foreach (T patchAsset in itemList)
5859
{
59-
if (itemPathSelector(patchAsset) is not {} filePath)
60+
if (itemPathSelector(patchAsset) is not { } filePath)
6061
{
6162
listFiltered.Add(patchAsset);
6263
continue;
6364
}
6465

66+
ConverterTool.NormalizePathInplaceNoTrim(filePath);
67+
6568
int indexOfAny = filePath.IndexOfAny(searchValues);
6669
if (indexOfAny >= 0)
6770
{
71+
Logger.LogWriteLine($"[StarRailInstall::FilterAssetList] Asset: {patchAsset} is ignored due to marked as deleted asset.",
72+
writeToLog: true);
6873
continue;
6974
}
7075

@@ -90,12 +95,9 @@ static ReadOnlySpan<char> GetFilePathFromJson(ReadOnlySpan<char> line)
9095
line = line[(firstIndexOf + first.Length)..];
9196
int endIndexOf = line.IndexOf(end);
9297

93-
if (endIndexOf <= 0)
94-
{
95-
return ReadOnlySpan<char>.Empty;
96-
}
97-
98-
return line[..endIndexOf];
98+
return endIndexOf <= 0
99+
? ReadOnlySpan<char>.Empty
100+
: line[..endIndexOf];
99101
}
100102
}
101103

@@ -127,4 +129,4 @@ private static void AddBothPersistentOrStreamingAssets(
127129
}
128130
}
129131
}
130-
}
132+
}

CollapseLauncher/Classes/InstallManagement/Zenless/ZenlessInstall.SophonPatch.cs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
using Hi3Helper.Sophon;
2-
using Hi3Helper.Sophon.Infos;
1+
using Hi3Helper;
32
using Hi3Helper.Sophon.Structs;
43
using System;
54
using System.Buffers;
65
using System.Collections.Generic;
76
using System.IO;
8-
using System.Runtime.CompilerServices;
97
using System.Threading;
108
using System.Threading.Tasks;
119
// ReSharper disable CheckNamespace
@@ -17,17 +15,9 @@ internal partial class ZenlessInstall
1715
{
1816
private const StringSplitOptions SplitOptions = StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries;
1917

20-
// ReSharper disable once StringLiteralTypo
21-
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<SophonChunksInfo>k__BackingField")]
22-
private static extern ref SophonChunksInfo GetChunkAssetChunksInfo(SophonAsset element);
23-
24-
// ReSharper disable once StringLiteralTypo
25-
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<SophonChunksInfoAlt>k__BackingField")]
26-
private static extern ref SophonChunksInfo GetChunkAssetChunksInfoAlt(SophonAsset element);
27-
2818
public override async Task FilterAssetList<T>(
29-
List<T> itemList,
30-
Func<T, string?> itemPathSelector,
19+
List<T> itemList,
20+
Func<T, string?> itemPathSelector,
3121
CancellationToken token)
3222
{
3323
HashSet<string> exceptMatchFieldHashSet = await GetExceptMatchFieldHashSet(token);
@@ -67,6 +57,8 @@ private static void FilterSophonAsset<T>(List<T> itemList, HashSet<string> excep
6757
if (asset is SophonIdentifiableProperty { MatchingField: { } assetMatchingField } &&
6858
exceptMatchFieldHashSet.Contains(assetMatchingField))
6959
{
60+
Logger.LogWriteLine($"[ZenlessInstall::FilterSophonAsset] Asset: {asset} is ignored due to marked as deleted asset.",
61+
writeToLog: true);
7062
continue;
7163
}
7264

@@ -114,4 +106,4 @@ internal static HashSet<string> CreateExceptMatchFieldHashSet(string exceptMatch
114106
return hashSetReturn;
115107
}
116108
}
117-
}
109+
}

CollapseLauncher/Classes/RepairManagement/Genshin/Repair.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
// ReSharper disable StringLiteralTypo
2222
// ReSharper disable CommentTypo
2323

24+
#nullable enable
2425
namespace CollapseLauncher
2526
{
2627
internal partial class GenshinRepair
@@ -46,7 +47,15 @@ private async Task<bool> Repair(List<PkgVersionProperties> repairAssetIndex, Can
4647
DownloadClient downloadClient = DownloadClient.CreateInstance(client);
4748

4849
// Get the Dispatcher Query
49-
QueryProperty queryProperty = await GetCachedDispatcherQuery(downloadClient.GetHttpClient(), token);
50+
QueryProperty? queryProperty = null;
51+
try
52+
{
53+
queryProperty = await GetCachedDispatcherQuery(downloadClient.GetHttpClient(), token);
54+
}
55+
catch (Exception ex)
56+
{
57+
LogWriteLine($"An error has occurred while parsing Persistent Manifests! {ex}", LogType.Warning, true);
58+
}
5059

5160
// Iterate repair asset
5261
ObservableCollection<IAssetProperty> assetProperty = [.. AssetEntry];
@@ -97,7 +106,10 @@ await Parallel.ForEachAsync(
97106
}
98107
}
99108

100-
await SavePersistentRevision(queryProperty, token);
109+
if (queryProperty != null)
110+
{
111+
await SavePersistentRevision(queryProperty, token);
112+
}
101113

102114
// Duplicate ctable.dat to ctable_streaming.dat
103115
string streamingAssetsPath = Path.Combine(GamePath, $"{ExecPrefix}_Data", "StreamingAssets");
@@ -157,7 +169,7 @@ private async Task RepairAssetTypeGeneric((PkgVersionProperties AssetIndex, IAss
157169
if (isUseSophonDownload)
158170
{
159171
ReadOnlySpan<char> splittedPath = asset.AssetIndex.remoteName.TrimStart('\\');
160-
if (!SophonAssetDictRefLookup.TryGetValue(splittedPath, out SophonAsset downloadAsSophon))
172+
if (!SophonAssetDictRefLookup.TryGetValue(splittedPath, out SophonAsset? downloadAsSophon))
161173
{
162174
throw new InvalidOperationException($"Asset {splittedPath} is marked as \"SophonGeneric\" but it wasn't included in the manifest");
163175
}

0 commit comments

Comments
 (0)