diff --git a/.gitignore b/.gitignore index 37a4aae..0a4f853 100644 --- a/.gitignore +++ b/.gitignore @@ -494,3 +494,4 @@ fabric.properties ### Custom ### launchSettings.json +.idea/.idea.ShinRyuModManager-CE/.idea/sonarlint.xml diff --git a/ParLibrary.Tests/SllzTests.cs b/ParLibrary.Tests/SllzTests.cs index e78a05c..b514032 100644 --- a/ParLibrary.Tests/SllzTests.cs +++ b/ParLibrary.Tests/SllzTests.cs @@ -26,7 +26,7 @@ public void TestSllz(byte compressionVersion) { var compressedBinaryFormat = (ParFile)ConvertFormat.With(typeof(Compressor), binaryFormat, parameters); var decompressedBinaryFormat = (ParFile)ConvertFormat.With(typeof(Decompressor), compressedBinaryFormat); - Assert.IsTrue(compressedBinaryFormat.Stream.Length < decompressedBinaryFormat.Stream.Length); + Assert.IsLessThan(decompressedBinaryFormat.Stream.Length, compressedBinaryFormat.Stream.Length); Assert.IsTrue(dataStream.Compare(decompressedBinaryFormat.Stream)); } } diff --git a/ParLibrary/Converter/ParArchiveWriter.cs b/ParLibrary/Converter/ParArchiveWriter.cs index 7a2532c..6bf90e2 100644 --- a/ParLibrary/Converter/ParArchiveWriter.cs +++ b/ParLibrary/Converter/ParArchiveWriter.cs @@ -246,22 +246,22 @@ private static void WriteNames(DataWriter writer, IEnumerable nodes) { } private static void WriteFolders(DataWriter writer, IEnumerable folders) { - foreach (var node in folders) { + foreach (var tags in folders.Select(x => x.Tags)) { var attributes = 0x00000010; - if (node.Tags.TryGetValue("DirectoryInfo", out var directoryInfo)) { + if (tags.TryGetValue("DirectoryInfo", out var directoryInfo)) { DirectoryInfo info = directoryInfo; attributes = (int)info.Attributes; } - if (node.Tags.TryGetValue("Attributes", out var attrs)) { + if (tags.TryGetValue("Attributes", out var attrs)) { attributes = (int)attrs; } - writer.Write((int)node.Tags["FolderCount"]); - writer.Write((int)node.Tags["FirstFolderIndex"]); - writer.Write((int)node.Tags["FileCount"]); - writer.Write((int)node.Tags["FirstFileIndex"]); + writer.Write((int)tags["FolderCount"]); + writer.Write((int)tags["FirstFolderIndex"]); + writer.Write((int)tags["FileCount"]); + writer.Write((int)tags["FirstFileIndex"]); writer.Write(attributes); writer.Write(0x00000000); writer.Write(0x00000000); @@ -275,20 +275,16 @@ private static void WriteFiles(DataWriter writer, IEnumerable files, long foreach (var node in files) { var parFile = node.GetFormatAs(); - if (parFile == null) { + if (parFile == null) continue; - } - - if (node.Stream!.Length > 2048) { - blockSize = 2048 + (-node.Stream.Length % 2048); + + var streamLength = node.Stream!.Length; + + if (streamLength > 2048 || streamLength >= blockSize) { + blockSize = 2048 + (-streamLength % 2048); dataPosition = Align(dataPosition, 2048); } else { - if (node.Stream.Length < blockSize) { - blockSize -= node.Stream.Length; - } else { - blockSize = 2048 + (-node.Stream.Length % 2048); - dataPosition = Align(dataPosition, 2048); - } + blockSize -= streamLength; } ulong seconds = 0; @@ -296,18 +292,16 @@ private static void WriteFiles(DataWriter writer, IEnumerable files, long if (!parameters.ResetFileDates) { var date = parFile.FileDate; - var baseDate = new DateTime(1970, 1, 1); + var baseDate = DateTime.UnixEpoch; if (node.Tags.TryGetValue("Timestamp", out var timestamp)) { date = baseDate.AddSeconds(timestamp); } - if (node.Tags.TryGetValue("FileInfo", out var fileInfo)) { - if (fileInfo is FileInfo info) { - attributes = HandleAttributes(info); - - date = info.LastWriteTime; - } + if (node.Tags.TryGetValue("FileInfo", out var fileInfo) && fileInfo is FileInfo info) { + attributes = HandleAttributes(info); + + date = info.LastWriteTime; } seconds = (ulong)(date - baseDate).TotalSeconds; diff --git a/ParLibrary/ParFile.cs b/ParLibrary/ParFile.cs index f44bebf..bda8dbf 100644 --- a/ParLibrary/ParFile.cs +++ b/ParLibrary/ParFile.cs @@ -15,10 +15,7 @@ public class ParFile : BinaryFormat, IConverter { /// Initializes a new instance of the class. /// public ParFile() { - CanBeCompressed = true; - IsCompressed = false; DecompressedSize = 0; - Attributes = 0x00000020; FileDate = DateTime.Now; } @@ -29,10 +26,7 @@ public ParFile() { public ParFile(DataStream stream) : base(stream) { ArgumentNullException.ThrowIfNull(stream); - CanBeCompressed = true; - IsCompressed = false; DecompressedSize = (uint)stream.Length; - Attributes = 0x00000020; FileDate = DateTime.Now; } @@ -43,18 +37,15 @@ public ParFile(DataStream stream) : base(stream) { /// Start offset. /// Data length. public ParFile(DataStream stream, long offset, long length) : base(stream, offset, length) { - CanBeCompressed = true; - IsCompressed = false; DecompressedSize = (uint)length; - Attributes = 0x00000020; FileDate = DateTime.Now; } - + /// /// Gets or sets a value indicating whether the file can be compressed. /// - public bool CanBeCompressed { get; init; } - + public bool CanBeCompressed { get; init; } = true; + /// /// Gets or sets a value indicating whether the file is compressed. /// @@ -64,32 +55,24 @@ public ParFile(DataStream stream, long offset, long length) : base(stream, offse /// Gets or sets the file size (decompressed). /// public uint DecompressedSize { get; init; } - + /// /// Gets or sets the file attributes. /// - public int Attributes { get; init; } + public int Attributes { get; init; } = 0x00000020; /// /// Gets or sets the file date (as ulong). /// public ulong Timestamp { get; init; } - + /// /// Gets or sets the file date (as DateTime). /// public DateTime FileDate { - get { - var baseDate = new DateTime(1970, 1, 1); - - return baseDate.AddSeconds(Timestamp); - } - - private init { - var baseDate = new DateTime(1970, 1, 1); - - Timestamp = (ulong)(value - baseDate).TotalSeconds; - } + get => DateTime.UnixEpoch.AddSeconds(Timestamp); + + private init => Timestamp = (ulong)(value - DateTime.UnixEpoch).TotalSeconds; } /// diff --git a/ParLibrary/Sllz/Compressor.cs b/ParLibrary/Sllz/Compressor.cs index 299ca0b..e3e37a4 100644 --- a/ParLibrary/Sllz/Compressor.cs +++ b/ParLibrary/Sllz/Compressor.cs @@ -82,7 +82,7 @@ private static DataStream Compress(DataStream inputDataStream, CompressorParamet break; case 2 when inputDataStream.Length < 0x1B: - throw new FormatException($"SLLZv2: Input size must more than 0x1A."); + throw new FormatException("SLLZv2: Input size must more than 0x1A."); case 2: compressedDataStream = CompressV2(inputDataStream); @@ -135,9 +135,7 @@ private static DataStream CompressV1(DataStream inputDataStream) { outputData[flagPosition] = 0x00; outputPosition++; - if (outputPosition >= outputSize) { - throw new SllzCompressorException("Compressed size is bigger than original size."); - } + ThrowIfCompressedIsLarger(outputPosition, outputSize); while (inputPosition < inputData.Length) { var windowSize = Math.Min(inputPosition, MAX_WINDOW_SIZE); @@ -158,18 +156,14 @@ private static DataStream CompressV1(DataStream inputDataStream) { outputData[flagPosition] = 0x00; outputPosition++; - if (outputPosition >= outputSize) { - throw new SllzCompressorException("Compressed size is bigger than original size."); - } + ThrowIfCompressedIsLarger(outputPosition, outputSize); } outputData[outputPosition] = inputData[inputPosition]; inputPosition++; outputPosition++; - if (outputPosition >= outputSize) { - throw new SllzCompressorException("Compressed size is bigger than original size."); - } + ThrowIfCompressedIsLarger(outputPosition, outputSize); } else { currentFlag |= (byte)(1 << (7 - bitCount)); bitCount++; @@ -183,9 +177,7 @@ private static DataStream CompressV1(DataStream inputDataStream) { outputData[flagPosition] = 0x00; outputPosition++; - if (outputPosition >= outputSize) { - throw new SllzCompressorException("Compressed size is bigger than original size."); - } + ThrowIfCompressedIsLarger(outputPosition, outputSize); } var offset = (short)((match.Item1 - 1) << 4); @@ -195,16 +187,12 @@ private static DataStream CompressV1(DataStream inputDataStream) { outputData[outputPosition] = (byte)tuple; outputPosition++; - if (outputPosition >= outputSize) { - throw new SllzCompressorException("Compressed size is bigger than original size."); - } + ThrowIfCompressedIsLarger(outputPosition, outputSize); outputData[outputPosition] = (byte)(tuple >> 8); outputPosition++; - - if (outputPosition >= outputSize) { - throw new SllzCompressorException("Compressed size is bigger than original size."); - } + + ThrowIfCompressedIsLarger(outputPosition, outputSize); inputPosition += match.Item2; } @@ -281,4 +269,10 @@ private static byte[] ZlibCompress(byte[] decompressedData) { return outputMemoryStream.ToArray(); } + + private static void ThrowIfCompressedIsLarger(uint outputPosition, uint outputSize) { + if (outputPosition >= outputSize) { + throw new SllzCompressorException("Compressed size is bigger than original size."); + } + } } \ No newline at end of file diff --git a/ShinRyuModManager-CE/GameModel.cs b/ShinRyuModManager-CE/GameModel.cs index 19f83d9..11eccdd 100644 --- a/ShinRyuModManager-CE/GameModel.cs +++ b/ShinRyuModManager-CE/GameModel.cs @@ -85,7 +85,9 @@ public static void DoY5HActProcedure(MLO mlo) { try { new DirectoryInfo(outputFakeDir).Delete(true); - } catch { } + } catch { + // ignore + } } else { var outputPath = Path.Combine(parlessDir.FullName, dir.Name + ".par"); Gibbed.Yakuza0.Pack.Program.Main([dir.FullName], outputPath); diff --git a/ShinRyuModManager-CE/LibMeta.cs b/ShinRyuModManager-CE/LibMeta.cs index aa554b9..9d64493 100644 --- a/ShinRyuModManager-CE/LibMeta.cs +++ b/ShinRyuModManager-CE/LibMeta.cs @@ -1,7 +1,9 @@ +using JetBrains.Annotations; using ShinRyuModManager.Helpers; namespace ShinRyuModManager; +[UsedImplicitly] public class LibMeta { public Guid GUID { get; set; } public string Name { get; set; } diff --git a/ShinRyuModManager-CE/ModLoadOrder/MLO.cs b/ShinRyuModManager-CE/ModLoadOrder/MLO.cs index 9633891..075fd0f 100644 --- a/ShinRyuModManager-CE/ModLoadOrder/MLO.cs +++ b/ShinRyuModManager-CE/ModLoadOrder/MLO.cs @@ -9,10 +9,10 @@ public class MLO { private const uint VERSION = 0x020000; // 2.0 private const uint FILESIZE = 0x0; // Remaining faithful to RGG by adding a filesize that's not used - public readonly List Mods; - public readonly List Files; - public readonly List ParlessFolders; - public readonly List CpkFolders; + public List Mods { get; } + public List Files { get; } + public List ParlessFolders { get; } + public List CpkFolders { get; } public MLO(List modIndices, List mods, OrderedSet fileSet, List parlessFolders, Dictionary> cpkFolders) { var files = fileSet.ToList(); diff --git a/ShinRyuModManager-CE/ModLoadOrder/Mods/Mod.cs b/ShinRyuModManager-CE/ModLoadOrder/Mods/Mod.cs index 9aaf029..9d5ca09 100644 --- a/ShinRyuModManager-CE/ModLoadOrder/Mods/Mod.cs +++ b/ShinRyuModManager-CE/ModLoadOrder/Mods/Mod.cs @@ -136,13 +136,8 @@ public void AddFiles(string path, string check) { case "speech": cpkDataPath = GamePath.RemoveModPath(path); - if (GamePath.CurrentGame == Game.Yakuza5) { + if (GamePath.CurrentGame is Game.Yakuza5 or <= Game.YakuzaKiwami) { RepackCpKs.Add(cpkDataPath + ".cpk"); - //Log.Verbose("Adding CPK folder: {CpkDataPath}", cpkDataPath); - } else { - if (GamePath.CurrentGame <= Game.YakuzaKiwami) { - RepackCpKs.Add(cpkDataPath + ".cpk"); - } } break; @@ -264,10 +259,8 @@ public void AddFiles(string path, string check) { } protected static string CheckFolder(string name) { - foreach (var folder in Constants.IncompatiblePars.Where(name.StartsWith)) { - return folder; - } - - return ""; + var folder = Constants.IncompatiblePars.FirstOrDefault(name.StartsWith); + + return folder ?? string.Empty; } } diff --git a/ShinRyuModManager-CE/ModLoadOrder/Mods/ModInfo.cs b/ShinRyuModManager-CE/ModLoadOrder/Mods/ModInfo.cs index fc1c36c..8b728ba 100644 --- a/ShinRyuModManager-CE/ModLoadOrder/Mods/ModInfo.cs +++ b/ShinRyuModManager-CE/ModLoadOrder/Mods/ModInfo.cs @@ -3,8 +3,7 @@ namespace ShinRyuModManager.ModLoadOrder.Mods; -public partial class ModInfo : ObservableObject, IEquatable { - +public sealed partial class ModInfo : ObservableObject, IEquatable { [ObservableProperty] private string _name; [ObservableProperty] private bool _enabled; diff --git a/ShinRyuModManager-CE/ModMeta.cs b/ShinRyuModManager-CE/ModMeta.cs index ef24341..422c7d2 100644 --- a/ShinRyuModManager-CE/ModMeta.cs +++ b/ShinRyuModManager-CE/ModMeta.cs @@ -5,7 +5,7 @@ public class ModMeta { public string Author { get; internal set; } public string Version { get; internal set; } public string Description { get; internal set; } - public string Dependencies { get; internal init; } + public string Dependencies { get; internal set; } public static ModMeta GetPlaceholder() { return new ModMeta { diff --git a/ShinRyuModManager-CE/ParRepacker.cs b/ShinRyuModManager-CE/ParRepacker.cs index f63e31a..1b67ab7 100644 --- a/ShinRyuModManager-CE/ParRepacker.cs +++ b/ShinRyuModManager-CE/ParRepacker.cs @@ -207,7 +207,7 @@ private static List GetModFiles(string path) { // Add files in current directory foreach (var p in Directory.GetFiles(path).Where(f => !f.EndsWith(Constants.VORTEX_MANAGED_FILE)).Select(GamePath.GetDataPathFrom)) { files.Add(p); - Log.Verbose("Adding file: {file}", p); + Log.Verbose("Adding file: {File}", p); } // Get files for all subdirectories diff --git a/ShinRyuModManager-CE/Program.cs b/ShinRyuModManager-CE/Program.cs index c1b2400..19cb89d 100644 --- a/ShinRyuModManager-CE/Program.cs +++ b/ShinRyuModManager-CE/Program.cs @@ -110,12 +110,13 @@ private static async Task MainCLI(string[] args) { var list = new List(args); if (list.Contains("-h") || list.Contains("--help")) { - Log.Information("Usage: run without arguments to generate mod load order."); - - Log.Information(" run with \"-s\" or \"--silent\" flag to prevent checking for updates and remove prompts."); + Log.Information(""" + Usage: run without arguments to generate mod load order. + -s, --silent prevent checking for updates and remove prompts. + -h, --help show this message and exit. + """); //Log.Information(" run with \"-r\" or \"--run\" flag to run the game after the program finishes."); - Log.Information(" run with \"-h\" or \"--help\" flag to show this message and exit."); return; } @@ -270,7 +271,7 @@ internal static List PreRun() { _migrated = true; // Migrate old format to new - Log.Information("Old format load order file (" + Constants.TXT_OLD + ") was found. Importing to the new format..."); + Log.Information("Old format load order file ({TxtOld}) was found. Importing to the new format...", Constants.TXT_OLD); mods.AddRange(ConvertOldToNewModList(ReadModLoadOrderTxt(Constants.TXT_OLD)) .Where(n => !mods.Any(m => EqualModNames(m.Name, n.Name)))); @@ -402,8 +403,8 @@ private static void PostRun() { // Calculate the checksum for the game's exe to inform the user if their version might be unsupported if (LogLevel <= LogEventLevel.Warning && InvalidGameExe()) { - Log.Error("Warning: Game version is unrecognized. Please use the latest Steam version of the game."); - Log.Error("Shin Ryu Mod Manager will still generate the load order, but the game might CRASH or not function properly"); + Log.Error("Warning: Game version is unrecognized. Please use the latest Steam version of the game.\n" + + "Shin Ryu Mod Manager will still generate the load order, but the game might CRASH or not function properly"); } if (!_isSilent) { diff --git a/ShinRyuModManager-CE/ShinRyuModManager-CE.csproj b/ShinRyuModManager-CE/ShinRyuModManager-CE.csproj index a19f24d..ddc1e64 100644 --- a/ShinRyuModManager-CE/ShinRyuModManager-CE.csproj +++ b/ShinRyuModManager-CE/ShinRyuModManager-CE.csproj @@ -45,7 +45,8 @@ - + + diff --git a/ShinRyuModManager-CE/Utils.cs b/ShinRyuModManager-CE/Utils.cs index 4282f06..5d9faea 100644 --- a/ShinRyuModManager-CE/Utils.cs +++ b/ShinRyuModManager-CE/Utils.cs @@ -9,14 +9,14 @@ namespace ShinRyuModManager; public static class Utils { // Static to be used through project - public static readonly HttpClient Client = new HttpClient(); + public static HttpClient Client { get; } = new HttpClient(); public static string NormalizeNameLower(string path) { return NormalizeSeparator(path.ToLowerInvariant()); } public static string NormalizeToNodePath(string path) { - return NormalizeSeparator(path, NodeSystem.PathSeparator.ToCharArray()[0]); + return NormalizeSeparator(path, NodeSystem.PathSeparator[0]); } internal static bool IsFileLocked(string path) { diff --git a/Utils/AssemblyVersion.cs b/Utils/AssemblyVersion.cs index 2f98dfb..891e9e8 100644 --- a/Utils/AssemblyVersion.cs +++ b/Utils/AssemblyVersion.cs @@ -1,5 +1,4 @@ -using System.Diagnostics; -using System.Reflection; +using System.Reflection; namespace Utils; diff --git a/Utils/GameHash.cs b/Utils/GameHash.cs index 9ec51a3..fce478a 100644 --- a/Utils/GameHash.cs +++ b/Utils/GameHash.cs @@ -2,7 +2,7 @@ namespace Utils; -public class GameHash { +public static class GameHash { public static bool ValidateFile(string path, Game game) { try { //Xbox doesnt like being read!