Skip to content

Commit

Permalink
Adding basic repair function for ZZZ
Browse files Browse the repository at this point in the history
  • Loading branch information
neon-nyan committed Oct 7, 2024
1 parent 20480fe commit 9de578a
Show file tree
Hide file tree
Showing 7 changed files with 705 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CollapseLauncher/Classes/GamePropertyVault.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal GamePresetProperty(UIElement UIElementParent, RegionResourceProp APIRes
_GameVersion = new GameTypeZenlessVersion(UIElementParent, _APIResouceProp, GamePreset, GameName, GameRegion);
_GameSettings = new ZenlessSettings(_GameVersion);
_GameCache = null;
_GameRepair = null;
_GameRepair = new ZenlessRepair(UIElementParent, _GameVersion, _GameSettings as ZenlessSettings);

Check warning on line 63 in CollapseLauncher/Classes/GamePropertyVault.cs

View workflow job for this annotation

GitHub Actions / Qodana for .NET

Possible 'null' assignment to non-nullable entity

Possible 'null' assignment to non-nullable entity

Check warning

Code scanning / QDNET

Possible 'null' assignment to non-nullable entity Warning

Possible 'null' assignment to non-nullable entity
_GameInstall = new ZenlessInstall(UIElementParent, _GameVersion, _GameSettings as ZenlessSettings);
break;
default:
Expand Down
4 changes: 2 additions & 2 deletions CollapseLauncher/Classes/Helper/Metadata/PresetConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,8 @@ public SophonChunkUrls? LauncherResourceChunksURL
public bool? IsHideSocMedDesc { get; init; } = true;

#if !DEBUG
public bool? IsRepairEnabled { get; init; }
public bool? IsCacheUpdateEnabled { get; init; }
public bool? IsRepairEnabled { get; set; }
public bool? IsCacheUpdateEnabled { get; set; }
#else
public bool? IsRepairEnabled = true;
public bool? IsCacheUpdateEnabled = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
using Hi3Helper;
using Hi3Helper.Data;
using Hi3Helper.Shared.ClassStruct;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;

namespace CollapseLauncher
{
internal partial class ZenlessRepair
{
private async Task Check(List<FilePropertiesRemote> assetIndex, CancellationToken token)
{
List<FilePropertiesRemote> brokenAssetIndex = new List<FilePropertiesRemote>();

// Set Indetermined status as false
_status.IsProgressAllIndetermined = false;
_status.IsProgressPerFileIndetermined = false;

// Show the asset entry panel
_status.IsAssetEntryPanelShow = true;

// Await the task for parallel processing
try
{
// Reset stopwatch
RestartStopwatch();

// Iterate assetIndex and check it using different method for each type and run it in parallel
await Parallel.ForEachAsync(assetIndex, new ParallelOptions { MaxDegreeOfParallelism = _threadCount, CancellationToken = token }, async (asset, threadToken) =>
{
// Assign a task depends on the asset type
switch (asset.FT)
{
case FileType.Generic:
await CheckGenericAssetType(asset, brokenAssetIndex, threadToken);
break;
case FileType.Blocks:
// await CheckAssetType(asset, brokenAssetIndex, threadToken);
break;
case FileType.Audio:
// await CheckAssetType(asset, brokenAssetIndex, threadToken);
break;
case FileType.Video:
// await CheckAssetType(asset, brokenAssetIndex, threadToken);
break;
}
});
}
catch (AggregateException ex)
{
throw ex.Flatten().InnerExceptions.First();
}
catch (Exception)

Check warning on line 58 in CollapseLauncher/Classes/RepairManagement/Zenless/ZenlessRepair.Check.cs

View workflow job for this annotation

GitHub Actions / Qodana for .NET

Redundant catch clause

Catch clause is redundant

Check warning

Code scanning / QDNET

Redundant catch clause Warning

Catch clause is redundant
{
throw;
}

// Re-add the asset index with a broken asset index
assetIndex.Clear();
assetIndex.AddRange(brokenAssetIndex);
}

private async ValueTask CheckGenericAssetType(FilePropertiesRemote asset, List<FilePropertiesRemote> targetAssetIndex, CancellationToken token)
{
// Update activity status
_status.ActivityStatus = string.Format(Locale.Lang._GameRepairPage.Status6, StarRailRepairExtension.GetFileRelativePath(asset.N, _gamePath));

// Increment current total count
_progressAllCountCurrent++;

// Reset per file size counter
_progressPerFileSizeTotal = asset.S;
_progressPerFileSizeCurrent = 0;

// Get the file info
FileInfo fileInfo = new FileInfo(asset.N);

// Check if the file exist or has unmatched size
if (!fileInfo.Exists)
{
// Update the total progress and found counter
_progressAllSizeFound += asset.S;
_progressAllCountFound++;

// Set the per size progress
_progressPerFileSizeCurrent = asset.S;

// Increment the total current progress
_progressAllSizeCurrent += asset.S;

Dispatch(() => AssetEntry.Add(
new AssetProperty<RepairAssetType>(
Path.GetFileName(asset.N),
ConvertRepairAssetTypeEnum(asset.FT),
Path.GetDirectoryName(asset.N),
asset.S,
null,
null
)
));
targetAssetIndex.Add(asset);

Logger.LogWriteLine($"File [T: {asset.FT}]: {asset.N} is not found", LogType.Warning, true);

return;
}

// Skip CRC check if fast method is used
if (_useFastMethod)
{
return;
}

// Open and read fileInfo as FileStream
using (FileStream filefs = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
{
// If pass the check above, then do CRC calculation
// Additional: the total file size progress is disabled and will be incremented after this
byte[] localCRC = await CheckHashAsync(filefs, MD5.Create(), token);

// If local and asset CRC doesn't match, then add the asset
if (!IsArrayMatch(localCRC, asset.CRCArray))
{
_progressAllSizeFound += asset.S;
_progressAllCountFound++;

Dispatch(() => AssetEntry.Add(
new AssetProperty<RepairAssetType>(
Path.GetFileName(asset.N),
ConvertRepairAssetTypeEnum(asset.FT),
Path.GetDirectoryName(asset.N),
asset.S,
localCRC,
asset.CRCArray
)
));

// Mark the main block as "need to be repaired"
asset.IsBlockNeedRepair = true;
targetAssetIndex.Add(asset);

Logger.LogWriteLine($"File [T: {asset.FT}]: {asset.N} is broken! Index CRC: {asset.CRC} <--> File CRC: {HexTool.BytesToHexUnsafe(localCRC)}", LogType.Warning, true);
}
}
}

private RepairAssetType ConvertRepairAssetTypeEnum(FileType assetType) => assetType switch
{
FileType.Blocks => RepairAssetType.Block,
FileType.Audio => RepairAssetType.Audio,
FileType.Video => RepairAssetType.Video,
_ => RepairAssetType.General
};
}
}
Loading

0 comments on commit 9de578a

Please sign in to comment.