From 2a85c39c5ef743deb60890b306b236ea573fffd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Thu, 2 Jan 2025 05:48:13 +0100 Subject: [PATCH 01/57] Add ivXor of CPlugVehiclePhyTuning (ty Auris!) --- .../Engines/Plug/CPlugVehiclePhyTuning.cs | 26 +++++++++++++++++++ Src/GBX.NET/Serialization/GbxReader.cs | 10 +++---- 2 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs b/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs new file mode 100644 index 000000000..3d0b00f20 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs @@ -0,0 +1,26 @@ +using System.Text; + +namespace GBX.NET.Engines.Plug; + +public partial class CPlugVehiclePhyTuning +{ + public partial class Chunk090EB000 + { + public override void ReadWrite(CPlugVehiclePhyTuning n, GbxReaderWriter rw) + { + rw.Id(ref n.name); + rw.NodeRef(ref U01); + rw.Single(ref U02); + + if (rw.Reader?.Settings.EncryptionInitializer is not null) + { + if (n.name is null || n.name.Length < 4) + { + throw new InvalidOperationException("Name length must be at least 4 characters."); + } + + rw.Reader.Settings.EncryptionInitializer.Initialize(Encoding.ASCII.GetBytes(n.name.Substring(0, 4)), 0, 4); + } + } + } +} diff --git a/Src/GBX.NET/Serialization/GbxReader.cs b/Src/GBX.NET/Serialization/GbxReader.cs index 100186a85..3144389c2 100644 --- a/Src/GBX.NET/Serialization/GbxReader.cs +++ b/Src/GBX.NET/Serialization/GbxReader.cs @@ -2069,15 +2069,13 @@ internal bool TryInitializeDecryption(IClass node) { parentClassId = 0x07001000; } - - if (node is CPlugSurfaceGeom) + else if (baseType == typeof(CGameCtnBlockInfo)) { - parentClassId = 0x0902B000; + parentClassId = 0x24005000; } - - if (baseType == typeof(CGameCtnBlockInfo)) + else if (baseType == typeof(CPlugVehiclePhyTuning)) { - parentClassId = 0x24005000; + parentClassId = 0x0A02E000; } var parentClassIDBytes = BitConverter.GetBytes(parentClassId); From 0597677d4e68232f67350042133c2e493f14b126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Fri, 3 Jan 2025 20:09:44 +0100 Subject: [PATCH 02/57] Log about file/folder argument resolving --- .../InputArguments/DirectoryInputArgument.cs | 11 +++++++++-- .../InputArguments/FileInputArgument.cs | 4 +++- Src/GBX.NET.Tool.CLI/InputArguments/InputArgument.cs | 4 +++- .../InputArguments/StandardInputArgument.cs | 6 ++++-- .../InputArguments/StandardTextInputArgument.cs | 6 ++++-- .../InputArguments/UriInputArgument.cs | 7 ++++++- Src/GBX.NET.Tool.CLI/SpectreConsoleLogger.cs | 5 +++++ Src/GBX.NET.Tool.CLI/ToolInstanceMaker.cs | 11 +++++++++-- 8 files changed, 43 insertions(+), 11 deletions(-) diff --git a/Src/GBX.NET.Tool.CLI/InputArguments/DirectoryInputArgument.cs b/Src/GBX.NET.Tool.CLI/InputArguments/DirectoryInputArgument.cs index 35c364c6a..e953cc4a3 100644 --- a/Src/GBX.NET.Tool.CLI/InputArguments/DirectoryInputArgument.cs +++ b/Src/GBX.NET.Tool.CLI/InputArguments/DirectoryInputArgument.cs @@ -1,11 +1,12 @@  using GBX.NET.Exceptions; +using Microsoft.Extensions.Logging; namespace GBX.NET.Tool.CLI.InputArguments; public sealed record DirectoryInputArgument(string DirectoryPath) : InputArgument { - public override async Task ResolveAsync(CancellationToken cancellationToken) + public override Task ResolveAsync(ILogger logger, CancellationToken cancellationToken) { var files = Directory.EnumerateFiles(DirectoryPath, "*.*", SearchOption.AllDirectories); @@ -13,6 +14,7 @@ public sealed record DirectoryInputArgument(string DirectoryPath) : InputArgumen { try { + logger.LogInformation("Reading file {File}...", Path.GetFileName(file)); await using var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync: true); return await Gbx.ParseAsync(stream, cancellationToken: cancellationToken); } @@ -20,8 +22,13 @@ public sealed record DirectoryInputArgument(string DirectoryPath) : InputArgumen { return await File.ReadAllBytesAsync(file, cancellationToken); } + catch (Exception ex) + { + logger.LogError(ex, "Failed to read file {File}.", Path.GetFileName(file)); + return null; + } }); - return await Task.WhenAll(tasks); + return Task.FromResult((object?)tasks); } } diff --git a/Src/GBX.NET.Tool.CLI/InputArguments/FileInputArgument.cs b/Src/GBX.NET.Tool.CLI/InputArguments/FileInputArgument.cs index 89b929bff..e089a7ce9 100644 --- a/Src/GBX.NET.Tool.CLI/InputArguments/FileInputArgument.cs +++ b/Src/GBX.NET.Tool.CLI/InputArguments/FileInputArgument.cs @@ -1,14 +1,16 @@  using GBX.NET.Exceptions; +using Microsoft.Extensions.Logging; namespace GBX.NET.Tool.CLI.InputArguments; public sealed record FileInputArgument(string FilePath) : InputArgument { - public override async Task ResolveAsync(CancellationToken cancellationToken) + public override async Task ResolveAsync(ILogger logger, CancellationToken cancellationToken) { try { + logger.LogInformation("Reading file {File}...", Path.GetFileName(FilePath)); await using var stream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync: true); return await Gbx.ParseAsync(stream, cancellationToken: cancellationToken); } diff --git a/Src/GBX.NET.Tool.CLI/InputArguments/InputArgument.cs b/Src/GBX.NET.Tool.CLI/InputArguments/InputArgument.cs index 4f34967b9..7926e88e0 100644 --- a/Src/GBX.NET.Tool.CLI/InputArguments/InputArgument.cs +++ b/Src/GBX.NET.Tool.CLI/InputArguments/InputArgument.cs @@ -1,7 +1,9 @@  +using Microsoft.Extensions.Logging; + namespace GBX.NET.Tool.CLI.InputArguments; public abstract record InputArgument { - public abstract Task ResolveAsync(CancellationToken cancellationToken); + public abstract Task ResolveAsync(ILogger logger, CancellationToken cancellationToken); } diff --git a/Src/GBX.NET.Tool.CLI/InputArguments/StandardInputArgument.cs b/Src/GBX.NET.Tool.CLI/InputArguments/StandardInputArgument.cs index 53f4b3430..9e02e8619 100644 --- a/Src/GBX.NET.Tool.CLI/InputArguments/StandardInputArgument.cs +++ b/Src/GBX.NET.Tool.CLI/InputArguments/StandardInputArgument.cs @@ -1,8 +1,10 @@ -namespace GBX.NET.Tool.CLI.InputArguments; +using Microsoft.Extensions.Logging; + +namespace GBX.NET.Tool.CLI.InputArguments; public sealed record StandardInputArgument(Stream Stream) : InputArgument { - public override Task ResolveAsync(CancellationToken cancellationToken) + public override Task ResolveAsync(ILogger logger, CancellationToken cancellationToken) { return Task.FromResult((object?)Stream); } diff --git a/Src/GBX.NET.Tool.CLI/InputArguments/StandardTextInputArgument.cs b/Src/GBX.NET.Tool.CLI/InputArguments/StandardTextInputArgument.cs index 09fe0d487..da873df46 100644 --- a/Src/GBX.NET.Tool.CLI/InputArguments/StandardTextInputArgument.cs +++ b/Src/GBX.NET.Tool.CLI/InputArguments/StandardTextInputArgument.cs @@ -1,8 +1,10 @@ -namespace GBX.NET.Tool.CLI.InputArguments; +using Microsoft.Extensions.Logging; + +namespace GBX.NET.Tool.CLI.InputArguments; public sealed record StandardTextInputArgument(TextReader Reader) : InputArgument { - public override Task ResolveAsync(CancellationToken cancellationToken) + public override Task ResolveAsync(ILogger logger, CancellationToken cancellationToken) { return Task.FromResult((object?)Reader); } diff --git a/Src/GBX.NET.Tool.CLI/InputArguments/UriInputArgument.cs b/Src/GBX.NET.Tool.CLI/InputArguments/UriInputArgument.cs index f75539ac0..ab022d1af 100644 --- a/Src/GBX.NET.Tool.CLI/InputArguments/UriInputArgument.cs +++ b/Src/GBX.NET.Tool.CLI/InputArguments/UriInputArgument.cs @@ -1,23 +1,28 @@  using GBX.NET.Exceptions; +using Microsoft.Extensions.Logging; namespace GBX.NET.Tool.CLI.InputArguments; public sealed record UriInputArgument(HttpClient Http, Uri Uri) : InputArgument { - public override async Task ResolveAsync(CancellationToken cancellationToken) + public override async Task ResolveAsync(ILogger logger, CancellationToken cancellationToken) { + logger.LogInformation("Downloading {Uri}...", Uri); + using var response = await Http.GetAsync(Uri, cancellationToken); response.EnsureSuccessStatusCode(); try { + logger.LogInformation("Reading {Uri} as Gbx...", Uri); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken); return await Gbx.ParseAsync(stream, cancellationToken: cancellationToken); } catch (NotAGbxException) { + logger.LogInformation("Reading {Uri} as data...", Uri); return await response.Content.ReadAsByteArrayAsync(cancellationToken); } } diff --git a/Src/GBX.NET.Tool.CLI/SpectreConsoleLogger.cs b/Src/GBX.NET.Tool.CLI/SpectreConsoleLogger.cs index 372730402..17363a2a7 100644 --- a/Src/GBX.NET.Tool.CLI/SpectreConsoleLogger.cs +++ b/Src/GBX.NET.Tool.CLI/SpectreConsoleLogger.cs @@ -30,6 +30,11 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } AnsiConsole.MarkupLine($" {GetLevelString(logLevel)} {Markup.Escape(formatter(state, exception))}"); + + if (exception is not null) + { + AnsiConsole.WriteException(exception); + } } private static string GetLevelString(LogLevel level) => level switch diff --git a/Src/GBX.NET.Tool.CLI/ToolInstanceMaker.cs b/Src/GBX.NET.Tool.CLI/ToolInstanceMaker.cs index 5f08e8c2e..c60bf1709 100644 --- a/Src/GBX.NET.Tool.CLI/ToolInstanceMaker.cs +++ b/Src/GBX.NET.Tool.CLI/ToolInstanceMaker.cs @@ -282,7 +282,7 @@ private async IAsyncEnumerable EnumerateResolvedObjectsAsync([Enumerator // Resolve objects from input and cache them if (!resolvedInputs.TryGetValue(input, out var resolvedObject)) { - resolvedObject = await input.ResolveAsync(cancellationToken); + resolvedObject = await input.ResolveAsync(logger, cancellationToken); resolvedInputs.Add(input, resolvedObject); } @@ -303,7 +303,14 @@ private async IAsyncEnumerable EnumerateResolvedObjectsAsync([Enumerator continue; } - yield return obj; + if (obj is Task task) + { + yield return await task; + } + else + { + yield return obj; + } } } else From f49cea47a239d556f8453dbf229ead69fd7981b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Fri, 3 Jan 2025 20:16:21 +0100 Subject: [PATCH 03/57] Add Samples to CSceneVehicleCarMarksSamples --- .../Scene/CSceneVehicleCarMarksSamples.chunkl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Src/GBX.NET/Engines/Scene/CSceneVehicleCarMarksSamples.chunkl b/Src/GBX.NET/Engines/Scene/CSceneVehicleCarMarksSamples.chunkl index d796966e4..323d05ccc 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneVehicleCarMarksSamples.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneVehicleCarMarksSamples.chunkl @@ -13,6 +13,16 @@ CSceneVehicleCarMarksSamples 0x0A083000 version v1+ throw + Sample[] Samples + +archive Sample // SSceneVehicleCarkMarkSample typo lol int - if U01 > 0 - throw + int + int + int + int + int + int + int + int + int \ No newline at end of file From 3c68e36f07b0cfb44aa0277deb4687ac8a403e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 4 Jan 2025 03:18:41 +0100 Subject: [PATCH 04/57] Fix CGameCtnCollection not linking header chunks properly --- .../Engines/Game/CGameCtnCollection.chunkl | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl index bbd10d461..ab57e4b95 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl @@ -1,10 +1,10 @@ CGameCtnCollection 0x03033000 -0x000 // old header +0x000 (header, struct: SOldHeaderDesc) // old header id -0x001 // desc - versionb version +0x001 (header, struct: SHeaderDesc) // desc + versionb id Collection bool NeedUnlock v1+ @@ -36,6 +36,25 @@ CGameCtnCollection 0x03033000 v10+ bool? IsEditable +0x002 (header, struct: SHeaderCollectorFolders) + versionb + string FolderBlockInfo + string + string FolderDecoration + v1+ + v2- + string + v2+ + string + v3+ + string + v4+ + string + +0x003 (header, struct: SHeaderMenuIconsFolders) + versionb + string FolderMenusIcons + 0x008 // DefaultDecoration CGameCtnDecoration DefaultDecoration (external) From b3fcf3d07b067c826d6f0d5a0e60adbf3586ce47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 4 Jan 2025 03:56:05 +0100 Subject: [PATCH 05/57] Add missing FolderItem --- Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl index ab57e4b95..7c03deb12 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl @@ -39,7 +39,7 @@ CGameCtnCollection 0x03033000 0x002 (header, struct: SHeaderCollectorFolders) versionb string FolderBlockInfo - string + string FolderItem string FolderDecoration v1+ v2- From f23ed3633bb5b180c902e25b29ad027ca1d107f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 4 Jan 2025 04:36:05 +0100 Subject: [PATCH 06/57] Add remaining header strings --- Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl index 7c03deb12..54c73182c 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl @@ -45,11 +45,11 @@ CGameCtnCollection 0x03033000 v2- string v2+ - string + string FolderCardEventInfo v3+ - string + string FolderMacroBlockInfo v4+ - string + string FolderMacroDecals 0x003 (header, struct: SHeaderMenuIconsFolders) versionb From 7acdf68cc25205c97a6d44f203781523794369b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 4 Jan 2025 20:42:59 +0100 Subject: [PATCH 07/57] Link SortIndex in body --- Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl index 54c73182c..f665bfbf1 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl @@ -83,7 +83,7 @@ CGameCtnCollection 0x03033000 CPlugBitmap CollectionIconFid (external) 0x00E - int + int SortIndex 0x011 int From 4bf2053f276fdb3ce6742c1b67332c8e6ef0594a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 4 Jan 2025 21:05:34 +0100 Subject: [PATCH 08/57] Minor CGameCtnCollection tweaks --- Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl index f665bfbf1..e87ef58a7 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl @@ -103,7 +103,7 @@ CGameCtnCollection 0x03033000 float ColorVertexMax 0x018 - int + CMwNod rect vec2 vec2 @@ -138,8 +138,8 @@ CGameCtnCollection 0x03033000 float CameraMinHeight bool -0x01F - int[] // ParticleEmitterModelsFids? +0x01F // ParticleEmitterModelsFids + int[] ParticleEmitterModelsFids 0x020 // folders string FolderBlockInfo @@ -249,7 +249,7 @@ CGameCtnCollection 0x03033000 float? float? v1+ - int? + int? // VehicleStyles? v2+ CMwNod ItemPlacementGroups v3+ From d621bc215fe0c076e4e234a5003e4cbfc5e5cc96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 4 Jan 2025 21:15:51 +0100 Subject: [PATCH 09/57] Fix HasLightmaps for Chunk0304305B --- Src/GBX.NET/Engines/Game/CGameCtnChallenge.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnChallenge.cs b/Src/GBX.NET/Engines/Game/CGameCtnChallenge.cs index fcf08713b..e68f2a7f4 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnChallenge.cs +++ b/Src/GBX.NET/Engines/Game/CGameCtnChallenge.cs @@ -276,6 +276,7 @@ public UInt128? HashedPassword private bool hasLightmaps; [AppliedWithChunk] + [AppliedWithChunk] public bool HasLightmaps { get => hasLightmaps; set => hasLightmaps = value; } [AppliedWithChunk(sinceVersion: 9)] From 7d1ca9baaacc5b1515dc7c389c4d6a1737c59906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 5 Jan 2025 00:15:14 +0100 Subject: [PATCH 10/57] Add CarCanBeDirty (ty marosis) --- Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl index e87ef58a7..83926d1b0 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl @@ -153,8 +153,8 @@ CGameCtnCollection 0x03033000 0x022 // is water multi-height bool IsWaterMultiHeight -0x023 - bool +0x023 // CarCanBeDirty + bool? CarCanBeDirty 0x024 int From 9e4811a1fc2ad8986f32ca7ed88aea61414f9f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 5 Jan 2025 00:31:12 +0100 Subject: [PATCH 11/57] Fix CGameCtnCollection 0x038 v4- being broken --- .../Engines/Game/CGameCtnCollection.chunkl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl index 83926d1b0..9151dd644 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnCollection.chunkl @@ -234,13 +234,13 @@ CGameCtnCollection 0x03033000 float WaterGRefracPertub v7+ int // not seen in code - float CameraMinHeight - v3- - bool // CSystemFidsFolder something? - bool IsWaterMultiHeight - v2- - float - float WaterFogClampAboveDist + float CameraMinHeight + v3- + bool // CSystemFidsFolder something? + bool IsWaterMultiHeight + v2- + float + float WaterFogClampAboveDist 0x039 version @@ -337,6 +337,6 @@ archive Water v3+ float? v2+ - int? // NodeRef? + CMwNod v7+ int? // not seen in code From 3f173f98d825f41546a55d3d05e2715c12718f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Thu, 9 Jan 2025 02:44:41 +0100 Subject: [PATCH 12/57] Progress CSceneLayout --- Src/GBX.NET/Engines/Hms/CHmsFogPlane.chunkl | 1 + .../Engines/Hms/CHmsPrecalcRender.chunkl | 1 + Src/GBX.NET/Engines/Hms/CHmsZone.chunkl | 17 +++++++++++++++++ Src/GBX.NET/Engines/Scene/CScene.chunkl | 11 +++++++++++ Src/GBX.NET/Engines/Scene/CSceneGate.chunkl | 1 + Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl | 17 +++++++++++++++++ Src/GBX.NET/Engines/Scene/CSceneSector.chunkl | 14 ++++++++++++++ 7 files changed, 62 insertions(+) create mode 100644 Src/GBX.NET/Engines/Hms/CHmsFogPlane.chunkl create mode 100644 Src/GBX.NET/Engines/Hms/CHmsPrecalcRender.chunkl create mode 100644 Src/GBX.NET/Engines/Hms/CHmsZone.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CScene.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CSceneGate.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CSceneSector.chunkl diff --git a/Src/GBX.NET/Engines/Hms/CHmsFogPlane.chunkl b/Src/GBX.NET/Engines/Hms/CHmsFogPlane.chunkl new file mode 100644 index 000000000..b7004dc40 --- /dev/null +++ b/Src/GBX.NET/Engines/Hms/CHmsFogPlane.chunkl @@ -0,0 +1 @@ +CHmsFogPlane 0x06017000 \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Hms/CHmsPrecalcRender.chunkl b/Src/GBX.NET/Engines/Hms/CHmsPrecalcRender.chunkl new file mode 100644 index 000000000..abeb943fe --- /dev/null +++ b/Src/GBX.NET/Engines/Hms/CHmsPrecalcRender.chunkl @@ -0,0 +1 @@ +CHmsPrecalcRender 0x06011000 \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Hms/CHmsZone.chunkl b/Src/GBX.NET/Engines/Hms/CHmsZone.chunkl new file mode 100644 index 000000000..247e80930 --- /dev/null +++ b/Src/GBX.NET/Engines/Hms/CHmsZone.chunkl @@ -0,0 +1,17 @@ +CHmsZone 0x06004000 + +0x002 + CHmsFogPlane[]_deprec FogPlanes + data[28] + +0x003 + bool U01 + if U01 + vec3 MRPoint + vec3 MRNormal + +0x005 + CHmsPrecalcRender[]_deprec PrecalcRenders + +0x006 + CPlugBitmap BitmapCubeReflectHardSpecA \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CScene.chunkl b/Src/GBX.NET/Engines/Scene/CScene.chunkl new file mode 100644 index 000000000..9b83a2ca7 --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CScene.chunkl @@ -0,0 +1,11 @@ +CScene 0x0A001000 +- abstract + +0x003 + CSceneConfig SceneConfig + +0x004 + uint[] + +0x005 + CMotionManager[]_deprec MotionManagers (external) \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneGate.chunkl b/Src/GBX.NET/Engines/Scene/CSceneGate.chunkl new file mode 100644 index 000000000..de3865311 --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneGate.chunkl @@ -0,0 +1 @@ +CSceneGate 0x0A006000 \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl index e40896e7e..01585ac38 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl @@ -1 +1,18 @@ CSceneLayout 0x0A003000 +- inherits: CScene + +0x00C + int + +0x010 + float CameraFarZ + vec3 CameraClearColor + +0x014 + int + bool + box + iso4 + +0x018 + CSceneSector[]_deprec Sectors diff --git a/Src/GBX.NET/Engines/Scene/CSceneSector.chunkl b/Src/GBX.NET/Engines/Scene/CSceneSector.chunkl new file mode 100644 index 000000000..1c35f1f1c --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneSector.chunkl @@ -0,0 +1,14 @@ +CSceneSector 0x0A004000 + +0x000 + int Scene + CHmsZone Zone + +0x001 + iso4 + +0x002 + id + +0x004 + box \ No newline at end of file From e851e38540e7fda2785192a2d63e7cd2fdde45e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Thu, 9 Jan 2025 22:50:20 +0100 Subject: [PATCH 13/57] Complete Scene3d for TMF --- Resources/Wrap.txt | 1 - .../Engines/Graphic/GxLightAmbient.chunkl | 6 +++ .../Engines/Graphic/GxLightDirectional.chunkl | 22 +++++++++++ Src/GBX.NET/Engines/Hms/CHmsLight.chunkl | 17 +++++++++ Src/GBX.NET/Engines/Hms/CHmsPocEmitter.chunkl | 2 + Src/GBX.NET/Engines/Hms/CHmsZone.chunkl | 2 +- .../Engines/Motion/CMotionWeather.chunkl | 2 + Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl | 1 + Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl | 37 +++++++++++++++++++ Src/GBX.NET/Engines/Scene/CSceneLight.chunkl | 5 +++ Src/GBX.NET/Engines/Scene/CScenePath.chunkl | 1 + .../Engines/Scene/CSceneTrafficGraph.chunkl | 5 +++ .../Engines/Scene/CSceneTrafficGraph.cs | 31 ++++++++++++++++ .../Engines/Scene/CSceneTrafficPath.chunkl | 1 + 14 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 Src/GBX.NET/Engines/Graphic/GxLightAmbient.chunkl create mode 100644 Src/GBX.NET/Engines/Graphic/GxLightDirectional.chunkl create mode 100644 Src/GBX.NET/Engines/Hms/CHmsLight.chunkl create mode 100644 Src/GBX.NET/Engines/Hms/CHmsPocEmitter.chunkl create mode 100644 Src/GBX.NET/Engines/Motion/CMotionWeather.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CSceneLight.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CScenePath.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CSceneTrafficGraph.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CSceneTrafficGraph.cs create mode 100644 Src/GBX.NET/Engines/Scene/CSceneTrafficPath.chunkl diff --git a/Resources/Wrap.txt b/Resources/Wrap.txt index eb8f0f632..38ddc23d5 100644 --- a/Resources/Wrap.txt +++ b/Resources/Wrap.txt @@ -24,7 +24,6 @@ 08050000 090E5000 08051000 09126000 08053000 090BF000 -08055000 09125000 0805A000 090B2000 0805B000 090B3000 0900D000 0900F000 diff --git a/Src/GBX.NET/Engines/Graphic/GxLightAmbient.chunkl b/Src/GBX.NET/Engines/Graphic/GxLightAmbient.chunkl new file mode 100644 index 000000000..7522fa4b0 --- /dev/null +++ b/Src/GBX.NET/Engines/Graphic/GxLightAmbient.chunkl @@ -0,0 +1,6 @@ +GxLightAmbient 0x04005000 +- inherits: GxLight + +0x000 + float ShadeMinY + float ShadeMaxY \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Graphic/GxLightDirectional.chunkl b/Src/GBX.NET/Engines/Graphic/GxLightDirectional.chunkl new file mode 100644 index 000000000..6b1e3aad1 --- /dev/null +++ b/Src/GBX.NET/Engines/Graphic/GxLightDirectional.chunkl @@ -0,0 +1,22 @@ +GxLightDirectional 0x04007000 +- inherits: GxLightNotAmbient + +0x001 + bool UseBoundaryHint + vec3 BoundaryHintPos + +0x002 (base: 0x001) + base + float DazzleAngleMax + float DazzleIntensity + +0x003 + vec3 DblSidedRGB + +0x004 + vec3 ReverseRGB + float ReverseIntens + +0x005 + float EmittAngularSize + float FlareAngularSize \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Hms/CHmsLight.chunkl b/Src/GBX.NET/Engines/Hms/CHmsLight.chunkl new file mode 100644 index 000000000..955ba9b66 --- /dev/null +++ b/Src/GBX.NET/Engines/Hms/CHmsLight.chunkl @@ -0,0 +1,17 @@ +CHmsLight 0x0600C000 +- inherits: CHmsPocEmitter + +0x000 + int + GxLight MainGxLight + +0x001 (base: 0x000) + base + +0x002 (base: 0x001) + base + CPlugBitmap BitmapFlare (external) + +0x003 (base: 0x002) + base + CPlugBitmap BitmapSprite (external) \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Hms/CHmsPocEmitter.chunkl b/Src/GBX.NET/Engines/Hms/CHmsPocEmitter.chunkl new file mode 100644 index 000000000..ee7cf65b4 --- /dev/null +++ b/Src/GBX.NET/Engines/Hms/CHmsPocEmitter.chunkl @@ -0,0 +1,2 @@ +CHmsPocEmitter 0x0600B000 +- inherits: CHmsPoc \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Hms/CHmsZone.chunkl b/Src/GBX.NET/Engines/Hms/CHmsZone.chunkl index 247e80930..27552552e 100644 --- a/Src/GBX.NET/Engines/Hms/CHmsZone.chunkl +++ b/Src/GBX.NET/Engines/Hms/CHmsZone.chunkl @@ -14,4 +14,4 @@ CHmsZone 0x06004000 CHmsPrecalcRender[]_deprec PrecalcRenders 0x006 - CPlugBitmap BitmapCubeReflectHardSpecA \ No newline at end of file + CPlugBitmap BitmapCubeReflectHardSpecA (external) \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Motion/CMotionWeather.chunkl b/Src/GBX.NET/Engines/Motion/CMotionWeather.chunkl new file mode 100644 index 000000000..30537b4de --- /dev/null +++ b/Src/GBX.NET/Engines/Motion/CMotionWeather.chunkl @@ -0,0 +1,2 @@ +CMotionWeather 0x08054000 +- inherits: CMotionManaged \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl b/Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl new file mode 100644 index 000000000..95c9012be --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl @@ -0,0 +1 @@ +CSceneFxNod 0x0A03A000 \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl index 01585ac38..c076562ae 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl @@ -16,3 +16,40 @@ CSceneLayout 0x0A003000 0x018 CSceneSector[]_deprec Sectors + version + Mobil[] + SceneLoc[] + CSceneObject[]_deprec + SceneLoc[] + CSceneLight[]_deprec Lights (external) + SceneLoc[] + CSceneObject[]_deprec + SceneLoc[] + CSceneObject[]_deprec + SceneLoc[] + CSceneObject[]_deprec + SceneLoc[] + CSceneGate[]_deprec Gates + CScenePath[]_deprec Paths + CSceneTrafficGraph TrafficGraph + CSceneTrafficPath[]_deprec TrafficPaths + CSceneFxNod SceneFxNod (external) + +archive Mobil + int U01 + if U01 == -2 + CMwNod U02 + +archive SceneLoc + CMwNod + iso4 + +archive Unknown + CMwNod + id + int + CMwNod + id + int + iso4 + iso4 \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneLight.chunkl b/Src/GBX.NET/Engines/Scene/CSceneLight.chunkl new file mode 100644 index 000000000..155c8a89f --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneLight.chunkl @@ -0,0 +1,5 @@ +CSceneLight 0x0A00B000 +- inherits: CScenePoc + +0x000 + CHmsLight Light (direct) \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CScenePath.chunkl b/Src/GBX.NET/Engines/Scene/CScenePath.chunkl new file mode 100644 index 000000000..051ba3716 --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CScenePath.chunkl @@ -0,0 +1 @@ +CScenePath 0x0A008000 \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneTrafficGraph.chunkl b/Src/GBX.NET/Engines/Scene/CSceneTrafficGraph.chunkl new file mode 100644 index 000000000..290efb43c --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneTrafficGraph.chunkl @@ -0,0 +1,5 @@ +CSceneTrafficGraph 0x0A062000 + +0x004 + +0x005 \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneTrafficGraph.cs b/Src/GBX.NET/Engines/Scene/CSceneTrafficGraph.cs new file mode 100644 index 000000000..26ab95741 --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneTrafficGraph.cs @@ -0,0 +1,31 @@ +namespace GBX.NET.Engines.Scene; + +public partial class CSceneTrafficGraph +{ + public partial class Chunk0A062004 + { + public override void ReadWrite(CSceneTrafficGraph n, GbxReaderWriter rw) + { + var count1 = rw.Int32(); + var count2 = rw.Int32(); + + if (count1 > 0) + { + throw new Exception("CSceneTrafficGraph.Chunk0A062004: count1 > 0"); + } + + if (count2 > 0) + { + throw new Exception("CSceneTrafficGraph.Chunk0A062004: count2 > 0"); + } + } + } + + public partial class Chunk0A062005 + { + public override void ReadWrite(CSceneTrafficGraph n, GbxReaderWriter rw) + { + // for loop on count1 + } + } +} diff --git a/Src/GBX.NET/Engines/Scene/CSceneTrafficPath.chunkl b/Src/GBX.NET/Engines/Scene/CSceneTrafficPath.chunkl new file mode 100644 index 000000000..7ecbc0bb0 --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneTrafficPath.chunkl @@ -0,0 +1 @@ +CSceneTrafficPath 0x0A063000 \ No newline at end of file From b7035f4e333f8f3dda34899e4841d2a42dbff4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Thu, 9 Jan 2025 23:01:42 +0100 Subject: [PATCH 14/57] Name stuff (ty marosis) --- Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl index c076562ae..1e8891e51 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl @@ -17,18 +17,18 @@ CSceneLayout 0x0A003000 0x018 CSceneSector[]_deprec Sectors version - Mobil[] - SceneLoc[] + Mobil[] Scene + SceneLoc[] SceneLocations CSceneObject[]_deprec SceneLoc[] CSceneLight[]_deprec Lights (external) - SceneLoc[] - CSceneObject[]_deprec - SceneLoc[] - CSceneObject[]_deprec - SceneLoc[] - CSceneObject[]_deprec - SceneLoc[] + SceneLoc[] LightLocations + CSceneObject[]_deprec Sounds + SceneLoc[] SoundLocations + CSceneObject[]_deprec Locations + SceneLoc[] LocationLocations + CSceneObject[]_deprec Fields + SceneLoc[] FieldLocations CSceneGate[]_deprec Gates CScenePath[]_deprec Paths CSceneTrafficGraph TrafficGraph From 3d6d76bd2deb9a02ae259796b4a87be332eb54bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Fri, 10 Jan 2025 20:10:21 +0100 Subject: [PATCH 15/57] Tweaks --- Src/GBX.NET/Engines/Scene/CScene.chunkl | 9 ++++++++- Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Src/GBX.NET/Engines/Scene/CScene.chunkl b/Src/GBX.NET/Engines/Scene/CScene.chunkl index 9b83a2ca7..e59103ecd 100644 --- a/Src/GBX.NET/Engines/Scene/CScene.chunkl +++ b/Src/GBX.NET/Engines/Scene/CScene.chunkl @@ -8,4 +8,11 @@ CScene 0x0A001000 uint[] 0x005 - CMotionManager[]_deprec MotionManagers (external) \ No newline at end of file + CMotionManager[]_deprec MotionManagers (external) + +0x006 (ignore) + OldSceneMobil[] OldMobils + +archive OldSceneMobil + CMwNod (external) + CMwNod (external) \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl index 1e8891e51..b02f86831 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl @@ -17,7 +17,7 @@ CSceneLayout 0x0A003000 0x018 CSceneSector[]_deprec Sectors version - Mobil[] Scene + SceneMobil[] Scene SceneLoc[] SceneLocations CSceneObject[]_deprec SceneLoc[] @@ -35,10 +35,10 @@ CSceneLayout 0x0A003000 CSceneTrafficPath[]_deprec TrafficPaths CSceneFxNod SceneFxNod (external) -archive Mobil +archive SceneMobil int U01 if U01 == -2 - CMwNod U02 + CMwNod Mobil archive SceneLoc CMwNod From 0f793d054c6b4aae0d1851f0fd7a2e4735ada212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 12 Jan 2025 00:18:02 +0100 Subject: [PATCH 16/57] Replace ExternalData with ExternalNodes (ExternalData will return someday) --- Src/GBX.NET.PAK/Pak.cs | 58 +++++++++++++++++++++++++-- Src/GBX.NET/Components/GbxRefTable.cs | 43 ++++---------------- 2 files changed, 62 insertions(+), 39 deletions(-) diff --git a/Src/GBX.NET.PAK/Pak.cs b/Src/GBX.NET.PAK/Pak.cs index 1f976f2b7..269157a31 100644 --- a/Src/GBX.NET.PAK/Pak.cs +++ b/Src/GBX.NET.PAK/Pak.cs @@ -1,4 +1,5 @@ -using GBX.NET.Crypto; +using GBX.NET.Components; +using GBX.NET.Crypto; using GBX.NET.Exceptions; using GBX.NET.Serialization; using NativeSharpZlib; @@ -220,10 +221,61 @@ public Stream OpenFile(PakFile file, out EncryptionInitializer encryptionInitial } [Zomp.SyncMethodGenerator.CreateSyncVersion] - public async Task OpenGbxFileAsync(PakFile file, GbxReadSettings settings = default, CancellationToken cancellationToken = default) + public async Task OpenGbxFileAsync(PakFile file, GbxReadSettings settings = default, bool importExternalNodesFromRefTable = false, IDictionary? fileHashes = default, CancellationToken cancellationToken = default) { using var stream = OpenFile(file, out var encryptionInitializer); - return await Gbx.ParseAsync(stream, settings with { EncryptionInitializer = encryptionInitializer }, cancellationToken); + var gbx = await Gbx.ParseAsync(stream, settings with { EncryptionInitializer = encryptionInitializer }, cancellationToken); + + if (gbx.RefTable is not null && importExternalNodesFromRefTable) + { + ImportExternalNodesFromRefTable(file, gbx.RefTable, settings, fileHashes); + } + + return gbx; + } + + private void ImportExternalNodesFromRefTable(PakFile file, GbxRefTable refTable, GbxReadSettings settings, IDictionary? fileHashes) + { + var ancestor = string.Join('\\', Enumerable.Repeat("..", refTable.AncestorLevel)); + var currentFileName = fileHashes?.TryGetValue(file.Name, out var resolvedFileName) == true ? resolvedFileName : file.Name; + var currentFileFolderPath = Path.GetDirectoryName(currentFileName); + var currentPakFileFolderPath = string.IsNullOrEmpty(currentFileFolderPath) ? file.FolderPath : Path.Combine(file.FolderPath, currentFileFolderPath); + + foreach (var refTableFile in refTable.Files) + { + var filePath = Path.GetRelativePath(Directory.GetCurrentDirectory(), Path.Combine(currentPakFileFolderPath, ancestor, refTableFile.FilePath)).Replace('/', '\\'); + + if (!Files.TryGetValue(filePath, out var refTableFileInPak)) + { + var directoryPath = Path.GetDirectoryName(filePath); + var fileName = Path.GetFileName(filePath); + + while (true) + { + var hash = MD5.Compute136(fileName); + + if (Files.TryGetValue(directoryPath + "\\" + hash, out refTableFileInPak)) + { + break; + } + + fileName = Path.Combine(Path.GetFileName(directoryPath)!, fileName); // maybe can rarely fail here? + directoryPath = Path.GetDirectoryName(directoryPath); + + if (string.IsNullOrEmpty(directoryPath)) + { + break; + } + } + } + + if (refTableFileInPak is null) + { + continue; + } + + refTable.ExternalNodes.Add(refTableFile.FilePath, () => OpenGbxFile(refTableFileInPak, settings)); + } } [Zomp.SyncMethodGenerator.CreateSyncVersion] diff --git a/Src/GBX.NET/Components/GbxRefTable.cs b/Src/GBX.NET/Components/GbxRefTable.cs index 4cae30a80..6709b3b59 100644 --- a/Src/GBX.NET/Components/GbxRefTable.cs +++ b/Src/GBX.NET/Components/GbxRefTable.cs @@ -16,10 +16,10 @@ public sealed class GbxRefTable /// public IReadOnlyCollection Resources { get; internal set; } = []; - public Dictionary ExternalData { get; } = []; + public Dictionary> ExternalNodes { get; set; } = []; /// - /// Directory path of the Gbx file used to resolve external files via the file system. File system is not used if this is null, instead, is used. + /// Directory path of the Gbx file used to resolve external files via the file system. File system is not used if this is null, instead, is used. /// public string? FileSystemPath { get; init; } @@ -38,6 +38,7 @@ private string GetFilePath(string filePath) public string GetFullFilePath(GbxRefTableFile file) => Path.GetFullPath(GetFilePath(file)); public string GetFullFilePath(UnlinkedGbxRefTableFile file) => Path.GetFullPath(GetFilePath(file)); + // TODO: should also have async variant in the future public CMwNod? LoadNode(GbxRefTableFile file, GbxReadSettings settings = default, bool exceptions = false) { if (file is null) @@ -88,37 +89,9 @@ private string GetFilePath(string filePath) } } - if (ExternalData.TryGetValue(file, out var data)) + if (ExternalNodes?.TryGetValue(file.FilePath, out var nodFunc) == true) { - using var ms = new MemoryStream(data); - - var scope = logger?.BeginScope("External [{Length} bytes]", data.Length); - - try - { - var gbx = Gbx.Parse(ms, settings); - - scope?.Dispose(); - - if (gbx.Node is null) - { - logger?.LogWarning("Failed to load node from External [{Length} bytes] ({Gbx})", data.Length, gbx); - } - - return gbx.Node; - } - catch (Exception ex) - { - scope?.Dispose(); - logger?.LogError(ex, "Failed to load node from file: {Length} bytes", data.Length); - - if (exceptions) - { - throw; - } - - return default; - } + return nodFunc(); } return default; @@ -149,11 +122,9 @@ public GbxRefTable DeepClone() FileSystemPath = FileSystemPath }; - foreach (var pair in ExternalData) + foreach (var pair in ExternalNodes) { - // TODO: Deep clone file or not? - var file = new GbxRefTableFile(refTable, pair.Key.Flags, pair.Key.UseFile, pair.Key.FilePath); - refTable.ExternalData.Add(file, pair.Value.ToArray()); + refTable.ExternalNodes.Add(pair.Key, pair.Value); } return refTable; From 0d00472ae61b48ddb234410d8acf0b2246a8af43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 12 Jan 2025 00:22:10 +0100 Subject: [PATCH 17/57] Fix EncryptionInitializer --- Src/GBX.NET.PAK/Pak.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Src/GBX.NET.PAK/Pak.cs b/Src/GBX.NET.PAK/Pak.cs index 269157a31..ec722e415 100644 --- a/Src/GBX.NET.PAK/Pak.cs +++ b/Src/GBX.NET.PAK/Pak.cs @@ -220,15 +220,27 @@ public Stream OpenFile(PakFile file, out EncryptionInitializer encryptionInitial return new NativeZlibStream(blowfish, CompressionMode.Decompress); } + /// + /// Attempts to open the Gbx file from Pak. If the file is not a Gbx file, is thrown. + /// + /// + /// + /// + /// + /// + /// [Zomp.SyncMethodGenerator.CreateSyncVersion] public async Task OpenGbxFileAsync(PakFile file, GbxReadSettings settings = default, bool importExternalNodesFromRefTable = false, IDictionary? fileHashes = default, CancellationToken cancellationToken = default) { using var stream = OpenFile(file, out var encryptionInitializer); - var gbx = await Gbx.ParseAsync(stream, settings with { EncryptionInitializer = encryptionInitializer }, cancellationToken); + + var settingsWithEncryption = settings with { EncryptionInitializer = encryptionInitializer }; + + var gbx = await Gbx.ParseAsync(stream, settingsWithEncryption, cancellationToken); if (gbx.RefTable is not null && importExternalNodesFromRefTable) { - ImportExternalNodesFromRefTable(file, gbx.RefTable, settings, fileHashes); + ImportExternalNodesFromRefTable(file, gbx.RefTable, settingsWithEncryption, fileHashes); } return gbx; From 713517528f0ecaaa1ea32fb0d1b431afe790fd71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 12 Jan 2025 00:32:00 +0100 Subject: [PATCH 18/57] Mark deep clone as experimental --- Src/GBX.NET/Components/GbxBody.cs | 6 ++++++ Src/GBX.NET/Components/GbxHeaderOfT.cs | 6 ++++++ Src/GBX.NET/Components/GbxHeaderUnknown.cs | 6 ++++++ Src/GBX.NET/Components/GbxRefTable.cs | 6 ++++++ Src/GBX.NET/Engines/MwFoundations/CMwNod.cs | 12 ++++++++++++ Src/GBX.NET/Gbx.cs | 12 +++++++++++- Src/GBX.NET/Serialization/Chunking/Chunk.cs | 12 ++++++++++++ 7 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Src/GBX.NET/Components/GbxBody.cs b/Src/GBX.NET/Components/GbxBody.cs index acd255498..dd1c29615 100644 --- a/Src/GBX.NET/Components/GbxBody.cs +++ b/Src/GBX.NET/Components/GbxBody.cs @@ -1,4 +1,7 @@ using System.Collections.Immutable; +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif using System.Text; namespace GBX.NET.Components; @@ -94,6 +97,9 @@ internal void Write(GbxWriter writer, MemoryStream uncompressedInputStream, GbxC new GbxBodyWriter(this, writer).Write(uncompressedInputStream, compressionOfBody); } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif public GbxBody DeepClone() => new() { RawData = RawData, diff --git a/Src/GBX.NET/Components/GbxHeaderOfT.cs b/Src/GBX.NET/Components/GbxHeaderOfT.cs index 31fc233cb..3549c2588 100644 --- a/Src/GBX.NET/Components/GbxHeaderOfT.cs +++ b/Src/GBX.NET/Components/GbxHeaderOfT.cs @@ -1,4 +1,7 @@ using GBX.NET.Managers; +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif namespace GBX.NET.Components; @@ -15,6 +18,9 @@ public sealed class GbxHeader(GbxHeaderBasic basic) : GbxHeader(basic) where classId ??= ClassManager.GetId() ?? throw new Exception("Class ID not available"); #endif +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif #if NETSTANDARD2_0 public override GbxHeader DeepClone() => new GbxHeader(Basic); #else diff --git a/Src/GBX.NET/Components/GbxHeaderUnknown.cs b/Src/GBX.NET/Components/GbxHeaderUnknown.cs index 487e8de02..8515f8a24 100644 --- a/Src/GBX.NET/Components/GbxHeaderUnknown.cs +++ b/Src/GBX.NET/Components/GbxHeaderUnknown.cs @@ -1,4 +1,7 @@ using GBX.NET.Managers; +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif namespace GBX.NET.Components; @@ -12,6 +15,9 @@ public override string ToString() return $"GbxHeader ({ClassManager.GetName(ClassId)}, 0x{ClassId:X8}, unknown)"; } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif #if NETSTANDARD2_0 public override GbxHeader DeepClone() #else diff --git a/Src/GBX.NET/Components/GbxRefTable.cs b/Src/GBX.NET/Components/GbxRefTable.cs index 6709b3b59..19ccb017b 100644 --- a/Src/GBX.NET/Components/GbxRefTable.cs +++ b/Src/GBX.NET/Components/GbxRefTable.cs @@ -1,4 +1,7 @@ using Microsoft.Extensions.Logging; +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif namespace GBX.NET.Components; @@ -112,6 +115,9 @@ internal bool Write(GbxWriter writer, GbxHeader header, bool rawBody) return new GbxRefTableWriter(this, header, writer).Write(rawBody); } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif public GbxRefTable DeepClone() { var refTable = new GbxRefTable diff --git a/Src/GBX.NET/Engines/MwFoundations/CMwNod.cs b/Src/GBX.NET/Engines/MwFoundations/CMwNod.cs index 46a335137..c398f4362 100644 --- a/Src/GBX.NET/Engines/MwFoundations/CMwNod.cs +++ b/Src/GBX.NET/Engines/MwFoundations/CMwNod.cs @@ -3,6 +3,9 @@ using Microsoft.Extensions.Logging; using System.Diagnostics; using System.Text; +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif namespace GBX.NET.Engines.MwFoundations; @@ -642,6 +645,9 @@ public virtual void ReadWrite(GbxReaderWriter rw) return chunk; } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif public virtual CMwNod DeepClone() { var clone = (CMwNod)MemberwiseClone(); @@ -649,6 +655,9 @@ public virtual CMwNod DeepClone() return clone; } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif IClass IClass.DeepClone() { var clone = (IClass)MemberwiseClone(); @@ -656,6 +665,9 @@ IClass IClass.DeepClone() return clone; } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif protected void DeepCloneChunks(IClass dest) { if (chunks is null) diff --git a/Src/GBX.NET/Gbx.cs b/Src/GBX.NET/Gbx.cs index c178e88ed..3765d021b 100644 --- a/Src/GBX.NET/Gbx.cs +++ b/Src/GBX.NET/Gbx.cs @@ -70,8 +70,9 @@ static abstract TVersion ParseHeaderNode(Stream stream, GbxRea static abstract TVersion ParseHeaderNode(string filePath, GbxReadSettings settings = default) where TClass : CMwNod, TVersion, new() where TVersion : IClassVersion; -#endif + [Experimental("GBXNET10001")] +#endif IGbx DeepClone(); } @@ -161,6 +162,9 @@ public override string ToString() return GbxPath.GetFileNameWithoutExtension(FilePath); } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif public virtual Gbx DeepClone() => new(Header.DeepClone(), Body.DeepClone()) { FilePath = FilePath, @@ -173,6 +177,9 @@ public override string ToString() ClassIdRemapMode = ClassIdRemapMode }; +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif IGbx IGbx.DeepClone() => DeepClone(); [Zomp.SyncMethodGenerator.CreateSyncVersion] @@ -1007,6 +1014,9 @@ public override string ToString() return $"Gbx<{typeof(T).Name}> ({ClassManager.GetName(Header.ClassId)}, 0x{Header.ClassId:X8})"; } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif #if NETSTANDARD2_0 public override Gbx DeepClone() => new Gbx((GbxHeader)Header.DeepClone(), Body.DeepClone(), (T)Node.DeepClone()) #else diff --git a/Src/GBX.NET/Serialization/Chunking/Chunk.cs b/Src/GBX.NET/Serialization/Chunking/Chunk.cs index 2d35c8418..eaf980c69 100644 --- a/Src/GBX.NET/Serialization/Chunking/Chunk.cs +++ b/Src/GBX.NET/Serialization/Chunking/Chunk.cs @@ -1,4 +1,7 @@ using GBX.NET.Managers; +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif namespace GBX.NET.Serialization.Chunking; @@ -15,6 +18,9 @@ public interface IChunk bool Ignore { get; } GameVersion GameVersion { get; } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif IChunk DeepClone(); } @@ -49,8 +55,14 @@ public virtual void Read(IClass n, GbxReader r) { } /// public virtual void Write(IClass n, GbxWriter w) { } +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif public abstract Chunk DeepClone(); +#if NET8_0_OR_GREATER + [Experimental("GBXNET10001")] +#endif IChunk IChunk.DeepClone() => DeepClone(); public override string ToString() => $"{ClassManager.GetName(Id & 0xFFFFF000)} chunk 0x{Id:X8}{(this is IVersionable v ? $" [v{v.Version}]" : "")}"; From 1704d32364cb4245e418a78799f22fa9ca04a6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 12 Jan 2025 01:59:27 +0100 Subject: [PATCH 19/57] Update NativeSharpZlib --- Src/GBX.NET.PAK/GBX.NET.PAK.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/GBX.NET.PAK/GBX.NET.PAK.csproj b/Src/GBX.NET.PAK/GBX.NET.PAK.csproj index 1790e32d3..2919d42aa 100644 --- a/Src/GBX.NET.PAK/GBX.NET.PAK.csproj +++ b/Src/GBX.NET.PAK/GBX.NET.PAK.csproj @@ -45,7 +45,7 @@ all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 8a0e6ea5a221852ad3f4b5ab59d14207e70b7de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 12 Jan 2025 02:46:53 +0100 Subject: [PATCH 20/57] Recognize newer paks --- Src/GBX.NET.PAK/Pak.cs | 117 ++++++++++++++++++--------------- Src/GBX.NET.PAK/Pak6.cs | 132 ++++++++++++++++++++++++++++++++++++-- Tools/PakToZip/Program.cs | 14 +++- 3 files changed, 206 insertions(+), 57 deletions(-) diff --git a/Src/GBX.NET.PAK/Pak.cs b/Src/GBX.NET.PAK/Pak.cs index ec722e415..927351d1b 100644 --- a/Src/GBX.NET.PAK/Pak.cs +++ b/Src/GBX.NET.PAK/Pak.cs @@ -10,7 +10,7 @@ namespace GBX.NET.PAK; -public sealed partial class Pak : IDisposable +public partial class Pak : IDisposable #if NET5_0_OR_GREATER , IAsyncDisposable #endif @@ -23,36 +23,28 @@ public sealed partial class Pak : IDisposable private const string PakListFileName = "packlist.dat"; private readonly Stream stream; - private readonly byte[] key; - private readonly byte[] headerMD5; - private readonly int metadataStart; - private readonly int dataStart; + private readonly byte[]? key; + + private int metadataStart; + private int dataStart; public int Version { get; } - public int Flags { get; } - public ImmutableDictionary Files { get; } - - private Pak(Stream stream, - byte[] key, - int version, - byte[] headerMD5, - int metadataStart, - int dataStart, - int flags, - ImmutableDictionary files) + + public ulong HeaderIV { get; private set; } + public byte[]? HeaderMD5 { get; private set; } + public int Flags { get; private set; } + + public ImmutableDictionary Files { get; private set; } = ImmutableDictionary.Empty; + + internal Pak(Stream stream, byte[]? key, int version) { this.stream = stream; this.key = key; Version = version; - this.headerMD5 = headerMD5; - this.metadataStart = metadataStart; - this.dataStart = dataStart; - Flags = flags; - Files = files; } [Zomp.SyncMethodGenerator.CreateSyncVersion] - public static async Task ParseAsync(Stream stream, byte[] key, CancellationToken cancellationToken = default) + public static async Task ParseAsync(Stream stream, byte[]? key, CancellationToken cancellationToken = default) { var r = new GbxReader(stream); @@ -63,17 +55,28 @@ public static async Task ParseAsync(Stream stream, byte[] key, Cancellation var version = r.ReadInt32(); - if (version > 5) + var pak = await CreateBasePak(stream, r, key, version, cancellationToken); + pak.HeaderIV = r.ReadUInt64(); + + if (key is not null) { - throw new Exception($"Version >5 (actual: {version}) is not supported. Use Pak6 for this file."); + await pak.ReadEncryptedAsync(stream, cancellationToken); } - var headerIV = r.ReadUInt64(); + return pak; + } + + [Zomp.SyncMethodGenerator.CreateSyncVersion] + private static async ValueTask CreateBasePak(Stream stream, GbxReader r, byte[]? key, int version, CancellationToken cancellationToken) + { + if (version < 6) + { + return new Pak(stream, key, version); + } - var decryptStream = new BlowfishStream(stream, key, headerIV); - var decryptReader = new GbxReader(decryptStream); - - return await ParseEncryptedAsync(decryptReader, stream, version, key, cancellationToken); + var pak6 = new Pak6(stream, key, version); + await pak6.ReadUnencryptedHeaderAsync(r, version, cancellationToken); + return pak6; } public static async Task ParseAsync(string filePath, byte[] key, CancellationToken cancellationToken = default) @@ -89,29 +92,32 @@ public static Pak Parse(string filePath, byte[] key) } [Zomp.SyncMethodGenerator.CreateSyncVersion] - private static async Task ParseEncryptedAsync( - GbxReader r, - Stream originalStream, - int version, - byte[] key, - CancellationToken cancellationToken) + protected async Task ReadEncryptedAsync(Stream stream, CancellationToken cancellationToken) { - var headerMD5 = await r.ReadBytesAsync(16, cancellationToken); - var metadataStart = r.ReadInt32(); // offset to metadata section - var dataStart = r.ReadInt32(); + if (key is null) + { + throw new Exception("Encryption key is missing"); + } + + var decryptStream = new BlowfishStream(stream, key, HeaderIV); + var r = new GbxReader(decryptStream); + + HeaderMD5 = await r.ReadBytesAsync(16, cancellationToken); + metadataStart = r.ReadInt32(); // offset to metadata section + dataStart = r.ReadInt32(); - if (version >= 2) + if (Version >= 2) { var gbxHeadersSize = r.ReadInt32(); var gbxHeadersComprSize = r.ReadInt32(); } - if (version >= 3) + if (Version >= 3) { r.SkipData(16); // unused } - var flags = r.ReadInt32(); + Flags = r.ReadInt32(); var allFolders = ReadAllFolders(r); @@ -121,9 +127,7 @@ private static async Task ParseEncryptedAsync( ((IEncryptionInitializer)r.BaseStream).Initialize(nameBytes, 4, 4); } - var files = ReadAllFiles(r, allFolders); - - return new Pak(originalStream, key, version, headerMD5, metadataStart, dataStart, flags, files); + Files = ReadAllFiles(r, allFolders); } private static PakFolder[] ReadAllFolders(GbxReader r) @@ -199,6 +203,11 @@ private static IEnumerable RecurseFoldersToParent(int folderIndex, Pa public Stream OpenFile(PakFile file, out EncryptionInitializer encryptionInitializer) { + if (key is null) + { + throw new Exception("Encryption key is missing"); + } + stream.Position = dataStart + file.Offset; var ivBuffer = new byte[8]; @@ -240,13 +249,14 @@ public async Task OpenGbxFileAsync(PakFile file, GbxReadSettings settings = if (gbx.RefTable is not null && importExternalNodesFromRefTable) { - ImportExternalNodesFromRefTable(file, gbx.RefTable, settingsWithEncryption, fileHashes); + // this can miss some files from other Pak files + ImportExternalNodesFromRefTable(this, file, gbx.RefTable, settingsWithEncryption, fileHashes); } return gbx; } - private void ImportExternalNodesFromRefTable(PakFile file, GbxRefTable refTable, GbxReadSettings settings, IDictionary? fileHashes) + private static void ImportExternalNodesFromRefTable(Pak pak, PakFile file, GbxRefTable refTable, GbxReadSettings settings, IDictionary? fileHashes) { var ancestor = string.Join('\\', Enumerable.Repeat("..", refTable.AncestorLevel)); var currentFileName = fileHashes?.TryGetValue(file.Name, out var resolvedFileName) == true ? resolvedFileName : file.Name; @@ -257,7 +267,7 @@ private void ImportExternalNodesFromRefTable(PakFile file, GbxRefTable refTable, { var filePath = Path.GetRelativePath(Directory.GetCurrentDirectory(), Path.Combine(currentPakFileFolderPath, ancestor, refTableFile.FilePath)).Replace('/', '\\'); - if (!Files.TryGetValue(filePath, out var refTableFileInPak)) + if (!pak.Files.TryGetValue(filePath, out var refTableFileInPak)) { var directoryPath = Path.GetDirectoryName(filePath); var fileName = Path.GetFileName(filePath); @@ -266,7 +276,7 @@ private void ImportExternalNodesFromRefTable(PakFile file, GbxRefTable refTable, { var hash = MD5.Compute136(fileName); - if (Files.TryGetValue(directoryPath + "\\" + hash, out refTableFileInPak)) + if (pak.Files.TryGetValue(directoryPath + "\\" + hash, out refTableFileInPak)) { break; } @@ -286,7 +296,7 @@ private void ImportExternalNodesFromRefTable(PakFile file, GbxRefTable refTable, continue; } - refTable.ExternalNodes.Add(refTableFile.FilePath, () => OpenGbxFile(refTableFileInPak, settings)); + refTable.ExternalNodes.Add(refTableFile.FilePath, () => pak.OpenGbxFile(refTableFileInPak, settings)); } } @@ -324,7 +334,14 @@ public static async Task> BruteforceFileHashesAsync( bool onlyUsedHashes = true, CancellationToken cancellationToken = default) { - var pakList = await PakList.ParseAsync(Path.Combine(directoryPath, PakListFileName), game, cancellationToken); + var pakListFilePath = Path.Combine(directoryPath, PakListFileName); + + if (!File.Exists(pakListFilePath)) + { + return []; + } + + var pakList = await PakList.ParseAsync(pakListFilePath, game, cancellationToken); var allPossibleFileHashes = new Dictionary(); diff --git a/Src/GBX.NET.PAK/Pak6.cs b/Src/GBX.NET.PAK/Pak6.cs index 5bb20b5ff..51318048a 100644 --- a/Src/GBX.NET.PAK/Pak6.cs +++ b/Src/GBX.NET.PAK/Pak6.cs @@ -1,9 +1,133 @@ -namespace GBX.NET.PAK; +using GBX.NET.Serialization; -internal sealed class Pak6 +namespace GBX.NET.PAK; + +internal sealed partial class Pak6 : Pak { - public static Task ParseAsync(Stream stream, byte[] key, CancellationToken cancellationToken = default) + public byte[] Checksum { get; private set; } = []; + public uint HeaderFlags { get; private set; } + public int? HeaderMaxSize { get; private set; } + public int AuthorVersion { get; private set; } + public string AuthorLogin { get; private set; } = string.Empty; + public string AuthorNickname { get; private set; } = string.Empty; + public string AuthorZone { get; private set; } = string.Empty; + public string AuthorExtraInfo { get; private set; } = string.Empty; + public string Comments { get; private set; } = string.Empty; + public string CreationBuildInfo { get; private set; } = string.Empty; + public string AuthorUrl { get; private set; } = string.Empty; + public string? ManialinkUrl { get; private set; } + public string? DownloadUrl { get; private set; } + public DateTime? CreationDate { get; private set; } + public string? Xml { get; private set; } + public string? TitleId { get; private set; } + public string? UsageSubDir { get; private set; } + public IncludedPackHeader[] IncludedPacks { get; private set; } = []; + + internal Pak6(Stream stream, byte[]? key, int version) : base(stream, key, version) + { + } + + [Zomp.SyncMethodGenerator.CreateSyncVersion] + internal async Task ReadUnencryptedHeaderAsync(GbxReader r, int version, CancellationToken cancellationToken) + { + Checksum = await r.ReadBytesAsync(32, cancellationToken); + HeaderFlags = r.ReadUInt32(); + + if (version >= 15) + { + HeaderMaxSize = r.ReadInt32(); + } + + if (version >= 7) + { + AuthorVersion = r.ReadInt32(); + AuthorLogin = r.ReadString(); + AuthorNickname = r.ReadString(); + AuthorZone = r.ReadString(); + AuthorExtraInfo = r.ReadString(); + + if (version < 9) + { + Comments = r.ReadString(); + r.SkipData(16); + + if (version == 8) + { + CreationBuildInfo = r.ReadString(); + AuthorUrl = r.ReadString(); + } + } + else + { + ManialinkUrl = r.ReadString(); + + if (version >= 13) + { + DownloadUrl = r.ReadString(); + } + + CreationDate = r.ReadFileTime(); + Comments = r.ReadString(); + + if (version >= 12) + { + Xml = r.ReadString(); + TitleId = r.ReadString(); + } + + UsageSubDir = r.ReadString(); + CreationBuildInfo = r.ReadString(); + r.SkipData(16); + + if (version >= 10) + { + IncludedPacks = new IncludedPackHeader[r.ReadUInt32()]; + + for (var i = 0; i < IncludedPacks.Length; i++) + { + IncludedPacks[i] = await IncludedPackHeader.DeserializeAsync(r, version, cancellationToken); + } + } + } + } + } + + public sealed partial class IncludedPackHeader { - return Task.FromResult(new Pak6()); + public byte[] ContentsChecksum { get; private set; } = []; + public string Name { get; private set; } = string.Empty; + public int AuthorVersion { get; private set; } + public string AuthorLogin { get; private set; } = string.Empty; + public string AuthorNickName { get; private set; } = string.Empty; + public string AuthorZone { get; private set; } = string.Empty; + public string AuthorExtraInfo { get; private set; } = string.Empty; + public string InfoManialinkUrl { get; private set; } = string.Empty; + public DateTime CreationDate { get; private set; } + public uint IncludeDepth { get; private set; } + + [Zomp.SyncMethodGenerator.CreateSyncVersion] + internal static async Task DeserializeAsync(GbxReader r, int version, CancellationToken cancellationToken) + { + var includedPacksHeaders = new IncludedPackHeader + { + ContentsChecksum = await r.ReadBytesAsync(32, cancellationToken), + Name = r.ReadString(), + AuthorVersion = r.ReadInt32(), + AuthorLogin = r.ReadString(), + AuthorNickName = r.ReadString(), + AuthorZone = r.ReadString(), + AuthorExtraInfo = r.ReadString(), + InfoManialinkUrl = r.ReadString(), + CreationDate = r.ReadFileTime() + }; + includedPacksHeaders.Name = r.ReadString(); + + if (version >= 11) + { + includedPacksHeaders.IncludeDepth = r.ReadUInt32(); + } + + return includedPacksHeaders; + } } } diff --git a/Tools/PakToZip/Program.cs b/Tools/PakToZip/Program.cs index ac6be1339..4d8b00437 100644 --- a/Tools/PakToZip/Program.cs +++ b/Tools/PakToZip/Program.cs @@ -18,14 +18,22 @@ var hashes = await Pak.BruteforceFileHashesAsync(directoryPath, game, onlyUsedHashes: false); +var key = default(byte[]); + var packlistFileName = Path.Combine(directoryPath, "packlist.dat"); -var packlist = await PakList.ParseAsync(packlistFileName, game); -var key = packlist[Path.GetFileNameWithoutExtension(pakFileName).ToLowerInvariant()].Key; +if (File.Exists(packlistFileName)) +{ + Console.WriteLine("Reading packlist..."); + var packlist = await PakList.ParseAsync(packlistFileName, game); + key = packlist[Path.GetFileNameWithoutExtension(pakFileName).ToLowerInvariant()].Key; +} await using var fs = File.OpenRead(pakFileName); await using var pak = await Pak.ParseAsync(fs, key); +File.Delete(Path.ChangeExtension(pakFileName, ".zip")); + using var zip = ZipFile.Open(Path.ChangeExtension(pakFileName, ".zip"), ZipArchiveMode.Create); foreach (var file in pak.Files.Values) @@ -39,7 +47,7 @@ try { - var gbx = await pak.OpenGbxFileAsync(file); + var gbx = await pak.OpenGbxFileAsync(file, fileHashes: hashes); using var stream = entry.Open(); From 40fe7f6b57bed125d0090a385c9e75fd00b61f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 12 Jan 2025 03:07:17 +0100 Subject: [PATCH 21/57] Handle encrypted part --- Src/GBX.NET.PAK/Pak.cs | 22 ++++++++++++++++++++-- Src/GBX.NET.PAK/Pak6.cs | 17 +++++++++++------ Src/GBX.NET.PAK/PakFile.cs | 8 +++++++- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/Src/GBX.NET.PAK/Pak.cs b/Src/GBX.NET.PAK/Pak.cs index 927351d1b..a9139b246 100644 --- a/Src/GBX.NET.PAK/Pak.cs +++ b/Src/GBX.NET.PAK/Pak.cs @@ -112,9 +112,24 @@ protected async Task ReadEncryptedAsync(Stream stream, CancellationToken cancell var gbxHeadersComprSize = r.ReadInt32(); } + if (Version >= 14) + { + r.SkipData(16); // unused + + if (Version >= 16) + { + var fileSize = r.ReadUInt32(); + } + } + if (Version >= 3) { r.SkipData(16); // unused + + if (Version == 6 && this is Pak6 pak6) + { + pak6.ReadAuthorInfo(r); + } } Flags = r.ReadInt32(); @@ -151,7 +166,7 @@ private static PakFolder[] ReadAllFolders(GbxReader r) return allFolders; } - private static ImmutableDictionary ReadAllFiles(GbxReader r, PakFolder[] allFolders) + private ImmutableDictionary ReadAllFiles(GbxReader r, PakFolder[] allFolders) { var files = ImmutableDictionary.CreateBuilder(); @@ -165,6 +180,9 @@ private static ImmutableDictionary ReadAllFiles(GbxReader r, Pa var compressedSize = r.ReadInt32(); var offset = r.ReadInt32(); var classId = r.ReadUInt32(); // indicates the type of the file + var size = Version >= 17 ? r.ReadInt32() : default(int?); + var checksum = Version >= 14 ? r.ReadUInt128() : default(UInt128?); + var fileFlags = r.ReadUInt64(); var folderPath = string.Join(Path.DirectorySeparatorChar, RecurseFoldersToParent(folderIndex, allFolders) @@ -172,7 +190,7 @@ private static ImmutableDictionary ReadAllFiles(GbxReader r, Pa .Select(f => f.Name.TrimEnd('\\'))); var filePath = Path.Combine(folderPath, name); - var file = new PakFile(name, folderPath, classId, offset, uncompressedSize, compressedSize, fileFlags); + var file = new PakFile(name, folderPath, classId, offset, uncompressedSize, compressedSize, size, checksum, fileFlags); files[filePath] = file; } diff --git a/Src/GBX.NET.PAK/Pak6.cs b/Src/GBX.NET.PAK/Pak6.cs index 51318048a..9b8e05736 100644 --- a/Src/GBX.NET.PAK/Pak6.cs +++ b/Src/GBX.NET.PAK/Pak6.cs @@ -40,11 +40,7 @@ internal async Task ReadUnencryptedHeaderAsync(GbxReader r, int version, Cancell if (version >= 7) { - AuthorVersion = r.ReadInt32(); - AuthorLogin = r.ReadString(); - AuthorNickname = r.ReadString(); - AuthorZone = r.ReadString(); - AuthorExtraInfo = r.ReadString(); + ReadAuthorInfo(r); if (version < 9) { @@ -82,7 +78,7 @@ internal async Task ReadUnencryptedHeaderAsync(GbxReader r, int version, Cancell if (version >= 10) { IncludedPacks = new IncludedPackHeader[r.ReadUInt32()]; - + for (var i = 0; i < IncludedPacks.Length; i++) { IncludedPacks[i] = await IncludedPackHeader.DeserializeAsync(r, version, cancellationToken); @@ -92,6 +88,15 @@ internal async Task ReadUnencryptedHeaderAsync(GbxReader r, int version, Cancell } } + internal void ReadAuthorInfo(GbxReader r) + { + AuthorVersion = r.ReadInt32(); + AuthorLogin = r.ReadString(); + AuthorNickname = r.ReadString(); + AuthorZone = r.ReadString(); + AuthorExtraInfo = r.ReadString(); + } + public sealed partial class IncludedPackHeader { public byte[] ContentsChecksum { get; private set; } = []; diff --git a/Src/GBX.NET.PAK/PakFile.cs b/Src/GBX.NET.PAK/PakFile.cs index d7eff5bc2..df316a37b 100644 --- a/Src/GBX.NET.PAK/PakFile.cs +++ b/Src/GBX.NET.PAK/PakFile.cs @@ -8,6 +8,8 @@ public sealed class PakFile public int Offset { get; } public int UncompressedSize { get; } public int CompressedSize { get; } + public int? Size { get; } + public UInt128? Checksum { get; } public ulong Flags { get; } public bool IsCompressed => (Flags & 0x7C) != 0; @@ -18,7 +20,9 @@ public PakFile( uint classId, int offset, int uncompressedSize, - int compressedSize, + int compressedSize, + int? size, + UInt128? checksum, ulong flags) { Name = name; @@ -27,6 +31,8 @@ public PakFile( Offset = offset; UncompressedSize = uncompressedSize; CompressedSize = compressedSize; + Size = size; + Checksum = checksum; Flags = flags; } From ddfd3d2f145d9db1a652127492dc26b230090af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 12 Jan 2025 03:45:47 +0100 Subject: [PATCH 22/57] Add support for second key --- .../Exceptions/NotAPakException.cs | 8 +- Src/GBX.NET.PAK/Pak.cs | 75 ++++++++++++++----- Src/GBX.NET.PAK/Pak6.cs | 2 +- 3 files changed, 61 insertions(+), 24 deletions(-) diff --git a/Src/GBX.NET.PAK/Exceptions/NotAPakException.cs b/Src/GBX.NET.PAK/Exceptions/NotAPakException.cs index e4a2abef6..e7e14874d 100644 --- a/Src/GBX.NET.PAK/Exceptions/NotAPakException.cs +++ b/Src/GBX.NET.PAK/Exceptions/NotAPakException.cs @@ -1,9 +1,9 @@ -namespace GBX.NET.Exceptions; +namespace GBX.NET.PAK.Exceptions; [Serializable] public class NotAPakException : Exception { - public NotAPakException() : base("Pak data stream was not identified.") { } - public NotAPakException(string message) : base(message) { } - public NotAPakException(string message, Exception? innerException) : base(message, innerException) { } + public NotAPakException() : base("Pak data stream was not identified.") { } + public NotAPakException(string message) : base(message) { } + public NotAPakException(string message, Exception? innerException) : base(message, innerException) { } } diff --git a/Src/GBX.NET.PAK/Pak.cs b/Src/GBX.NET.PAK/Pak.cs index a9139b246..284906c50 100644 --- a/Src/GBX.NET.PAK/Pak.cs +++ b/Src/GBX.NET.PAK/Pak.cs @@ -1,6 +1,7 @@ using GBX.NET.Components; using GBX.NET.Crypto; using GBX.NET.Exceptions; +using GBX.NET.PAK.Exceptions; using GBX.NET.Serialization; using NativeSharpZlib; using System.Collections.Immutable; @@ -24,6 +25,7 @@ public partial class Pak : IDisposable private readonly Stream stream; private readonly byte[]? key; + private readonly byte[]? secondKey; private int metadataStart; private int dataStart; @@ -36,16 +38,32 @@ public partial class Pak : IDisposable public ImmutableDictionary Files { get; private set; } = ImmutableDictionary.Empty; - internal Pak(Stream stream, byte[]? key, int version) + internal Pak(Stream stream, byte[]? key, byte[]? secondKey, int version) { this.stream = stream; this.key = key; + this.secondKey = secondKey; Version = version; } + /// + /// Parses the Pak file from the stream. Should be disposed after use, as it keeps the file open (currently at least). + /// + /// Stream. + /// Key for main decryption, or only the header part for newer Pak format. + /// Alternative key to use for decrypting individual files. Ignored for TMF Pak (v3) format and older. + /// Cancellation token. + /// A task. The task result contains the parsed Pak format. + /// is null. + /// Stream is not Pak-formatted. [Zomp.SyncMethodGenerator.CreateSyncVersion] - public static async Task ParseAsync(Stream stream, byte[]? key, CancellationToken cancellationToken = default) + public static async Task ParseAsync(Stream stream, byte[]? key, byte[]? secondKey = null, CancellationToken cancellationToken = default) { + if (stream is null) + { + throw new ArgumentNullException(nameof(stream)); + } + var r = new GbxReader(stream); if (!r.ReadPakMagic()) @@ -55,7 +73,7 @@ public static async Task ParseAsync(Stream stream, byte[]? key, Cancellatio var version = r.ReadInt32(); - var pak = await CreateBasePak(stream, r, key, version, cancellationToken); + var pak = await CreateBasePak(stream, r, key, secondKey, version, cancellationToken); pak.HeaderIV = r.ReadUInt64(); if (key is not null) @@ -66,31 +84,50 @@ public static async Task ParseAsync(Stream stream, byte[]? key, Cancellatio return pak; } + /// + /// Parses the Pak file from file path. Should be disposed after use, as it keeps the file open (currently at least). + /// + /// File path. + /// Key for main decryption, or only the header part for newer Pak format. + /// Alternative key to use for decrypting individual files. Ignored for TMF Pak (v3) format and older. + /// Cancellation token. + /// A task. The task result contains the parsed Pak format. + /// is null. + /// Stream is not Pak-formatted. + public static async Task ParseAsync(string filePath, byte[] key, byte[]? secondKey = null, CancellationToken cancellationToken = default) + { + var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true); + return await ParseAsync(fs, key, secondKey, cancellationToken); + } + + /// + /// Parses the Pak file from file path. Should be disposed after use, as it keeps the file open (currently at least). + /// + /// File path. + /// Key for main decryption, or only the header part for newer Pak format. + /// Alternative key to use for decrypting individual files. Ignored for TMF Pak (v3) format and older. + /// Parsed Pak format. + /// is null. + /// Stream is not Pak-formatted. + public static Pak Parse(string filePath, byte[] key, byte[]? secondKey = null) + { + var fs = File.OpenRead(filePath); + return Parse(fs, key, secondKey); + } + [Zomp.SyncMethodGenerator.CreateSyncVersion] - private static async ValueTask CreateBasePak(Stream stream, GbxReader r, byte[]? key, int version, CancellationToken cancellationToken) + private static async ValueTask CreateBasePak(Stream stream, GbxReader r, byte[]? key, byte[]? secondKey, int version, CancellationToken cancellationToken) { if (version < 6) { - return new Pak(stream, key, version); + return new Pak(stream, key, secondKey, version); } - var pak6 = new Pak6(stream, key, version); + var pak6 = new Pak6(stream, headerKey: key, bodyKey: secondKey, version); await pak6.ReadUnencryptedHeaderAsync(r, version, cancellationToken); return pak6; } - public static async Task ParseAsync(string filePath, byte[] key, CancellationToken cancellationToken = default) - { - var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true); - return await ParseAsync(fs, key, cancellationToken); - } - - public static Pak Parse(string filePath, byte[] key) - { - var fs = File.OpenRead(filePath); - return Parse(fs, key); - } - [Zomp.SyncMethodGenerator.CreateSyncVersion] protected async Task ReadEncryptedAsync(Stream stream, CancellationToken cancellationToken) { @@ -431,7 +468,7 @@ public static async Task> BruteforceFileHashesAsync( continue; } - using var pak = await ParseAsync(fullFileName, pakInfo.Value.Key, cancellationToken); + using var pak = await ParseAsync(fullFileName, pakInfo.Value.Key, cancellationToken: cancellationToken); foreach (var file in pak.Files.Values) { diff --git a/Src/GBX.NET.PAK/Pak6.cs b/Src/GBX.NET.PAK/Pak6.cs index 9b8e05736..a5382a2b9 100644 --- a/Src/GBX.NET.PAK/Pak6.cs +++ b/Src/GBX.NET.PAK/Pak6.cs @@ -23,7 +23,7 @@ internal sealed partial class Pak6 : Pak public string? UsageSubDir { get; private set; } public IncludedPackHeader[] IncludedPacks { get; private set; } = []; - internal Pak6(Stream stream, byte[]? key, int version) : base(stream, key, version) + internal Pak6(Stream stream, byte[]? headerKey, byte[]? bodyKey, int version) : base(stream, headerKey, bodyKey, version) { } From 8f44effd59ac8083d6689a0d873f2bca57290947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 12 Jan 2025 05:06:46 +0100 Subject: [PATCH 23/57] Fix CPlugGameSkin header v8 --- Src/GBX.NET/Engines/Plug/CPlugGameSkin.chunkl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Src/GBX.NET/Engines/Plug/CPlugGameSkin.chunkl b/Src/GBX.NET/Engines/Plug/CPlugGameSkin.chunkl index ea7ca9792..816051318 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugGameSkin.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugGameSkin.chunkl @@ -15,6 +15,8 @@ CPlugGameSkin 0x090F4000 string v7+ int + v8+ + byte 0x003 string From 14b2f1d91961c1b99bfa13455033f44aedf9931e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 13 Jan 2025 13:20:20 +0100 Subject: [PATCH 24/57] Update README.md --- Src/GBX.NET/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Src/GBX.NET/README.md b/Src/GBX.NET/README.md index 44c6c7941..4443d7a93 100644 --- a/Src/GBX.NET/README.md +++ b/Src/GBX.NET/README.md @@ -11,6 +11,7 @@ For more details, see the main README. Due to the recently paced evolution of .NET, framework support has been limited only to a few ones compared to GBX.NET 1: +- .NET 9 - .NET 8 - .NET 6 - .NET Standard 2.0 @@ -180,13 +181,13 @@ Some of the common types to start with (a lot more are supported): | SystemConfig.Gbx | CSystemConfig | Yes | Yes | FidCache.Gbx | CMwRefBuffer | Yes | Yes | Profile.Gbx | CGamePlayerProfile | Up to TMF | Up to TMF -| Scores.Gbx | CGamePlayerScore | Yes | No +| Scores.Gbx | CGamePlayerScore | No | No ## Supported games Many *essential* Gbx files from many games are supported: -- **Trackmania (2020)**, July 2024 update +- **Trackmania (2020)**, December 2024 update - **ManiaPlanet 4**(.1), TM2/SM - **Trackmania Turbo** - ManiaPlanet 3, TM2/SM @@ -223,4 +224,4 @@ Without these people, this project wouldn't be what it is today (ordered by impa - Mika Kuijpers (TheMrMiku) - donadigo -And many thanks to every bug reporter! \ No newline at end of file +And many thanks to every bug reporter! From 52f40057cef5ae8a43d1d21e16fbe0982a9c7fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 13 Jan 2025 13:20:53 +0100 Subject: [PATCH 25/57] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a231d4916..1bc498ece 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ For any questions, open an issue, join the [GameBox Sandbox Discord server](http Many *essential* Gbx files from many games are supported: -- **Trackmania (2020)**, October 2024 update +- **Trackmania (2020)**, December 2024 update - **ManiaPlanet 4**(.1), TM2/SM - **Trackmania Turbo** - ManiaPlanet 3, TM2/SM @@ -87,7 +87,7 @@ Here are some of the known file types to start with: | LightMapCache.Gbx | [CHmsLightMapCache](Src/GBX.NET/Engines/Hms/CHmsLightMapCache.chunkl) | No | No | SystemConfig.Gbx | [CSystemConfig](Src/GBX.NET/Engines/System/CSystemConfig.chunkl) | Yes | Yes | FidCache.Gbx | [CMwRefBuffer](Src/GBX.NET/Engines/MwFoundations/CMwRefBuffer.chunkl) | Yes | Yes -| Scores.Gbx | [CGamePlayerScore](Src/GBX.NET/Engines/Game/CGamePlayerScore.chunkl) | Yes | No +| Scores.Gbx | [CGamePlayerScore](Src/GBX.NET/Engines/Game/CGamePlayerScore.chunkl) | No | No **Full list of supported file types is available in the [SUPPORTED GBX FILE TYPES](SUPPORTED_GBX_FILE_TYPES.md)**. From c2d3f1d642be12869428970bce1938dca1d87fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 18 Jan 2025 03:21:48 +0100 Subject: [PATCH 26/57] Fill CPlugMaterialCustom.Bitmap --- Src/GBX.NET/Engines/Plug/CPlugMaterialCustom.chunkl | 4 ++-- Src/GBX.NET/Engines/Plug/CPlugSolid2Model.chunkl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Src/GBX.NET/Engines/Plug/CPlugMaterialCustom.chunkl b/Src/GBX.NET/Engines/Plug/CPlugMaterialCustom.chunkl index edc8aa1b6..32ad78393 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugMaterialCustom.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugMaterialCustom.chunkl @@ -63,9 +63,9 @@ CPlugMaterialCustom 0x0903A000 string archive Bitmap - id + id Name int - CMwNod (external) + CMwNod Texture (external) v1+ int int diff --git a/Src/GBX.NET/Engines/Plug/CPlugSolid2Model.chunkl b/Src/GBX.NET/Engines/Plug/CPlugSolid2Model.chunkl index 46c183aa6..363b7d5d2 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugSolid2Model.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugSolid2Model.chunkl @@ -36,7 +36,7 @@ archive Light id U01 bool U02 if U02 - CPlugLight U03 + CPlugLight U03 (external) if !U02 string U04 iso4 U05 From 4de691fe76aa640ec1036ece8aa24cc82e19e1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 18 Jan 2025 18:31:34 +0100 Subject: [PATCH 27/57] Add CPlugShaderApply 0x007 --- Src/GBX.NET/Engines/Plug/CPlugShaderApply.chunkl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Src/GBX.NET/Engines/Plug/CPlugShaderApply.chunkl b/Src/GBX.NET/Engines/Plug/CPlugShaderApply.chunkl index eac6c8e64..7e4d6a0fe 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugShaderApply.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugShaderApply.chunkl @@ -25,6 +25,9 @@ CPlugShaderApply 0x09026000 0x006 int +0x007 + int + 0x008 int int From 05ffe74c83729437a3ff02bf77caa0ac3e6ce2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 18 Jan 2025 18:32:55 +0100 Subject: [PATCH 28/57] Support embedded shaders --- .../Extensions/Exporters/ObjExporter.cs | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/Src/GBX.NET/Extensions/Exporters/ObjExporter.cs b/Src/GBX.NET/Extensions/Exporters/ObjExporter.cs index 2e4df25d7..2e986f547 100644 --- a/Src/GBX.NET/Extensions/Exporters/ObjExporter.cs +++ b/Src/GBX.NET/Extensions/Exporters/ObjExporter.cs @@ -163,6 +163,8 @@ public static void Export(CPlugSolid solid, TextWriter objWriter, TextWriter mtl var positionsDict = mergeVerticesDigitThreshold.HasValue ? new Dictionary(new Vec3EqualityComparer(mergeVerticesDigitThreshold.Value)) : []; + var unknownMaterialDict = new Dictionary(); + foreach (var (t, loc) in tree.GetAllChildrenWithLocation(lod)) { if (t.Visual is null) @@ -175,7 +177,20 @@ public static void Export(CPlugSolid solid, TextWriter objWriter, TextWriter mtl continue; } - var materialName = t.ShaderFile is null ? "Unknown" : GbxPath.GetFileNameWithoutExtension(t.ShaderFile.FilePath); + string materialName; + if (t.ShaderFile is not null) + { + materialName = GbxPath.GetFileNameWithoutExtension(t.ShaderFile.FilePath); + } + else if (t.Shader is not null) + { + unknownMaterialDict[t.Shader] = unknownMaterialDict.Count; + materialName = "Unknown" + unknownMaterialDict.Count; + } + else + { + materialName = "Unknown"; + } if (!materials.Contains(materialName)) { @@ -304,17 +319,24 @@ public static void Export(CPlugSolid solid, TextWriter objWriter, TextWriter mtl continue; } - if (t.ShaderFile is null) + if (visual.IndexBuffer is null) { continue; } - if (visual.IndexBuffer is null) + string materialName; + if (t.ShaderFile is not null) { - continue; + materialName = GbxPath.GetFileNameWithoutExtension(t.ShaderFile.FilePath); + } + else if (t.Shader is not null) + { + materialName = "Unknown" + unknownMaterialDict[t.Shader]; + } + else + { + materialName = "Unknown"; } - - var materialName = GbxPath.GetFileNameWithoutExtension(t.ShaderFile.FilePath); objWriter.WriteLine("g {0}", materialName); objWriter.WriteLine("usemtl {0}", materialName); From b58567644e0666d3e9b19c00270fa031b8778554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 18 Jan 2025 18:51:35 +0100 Subject: [PATCH 29/57] Fix CPlugBitmapApply remap bug --- Resources/Wrap.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Wrap.txt b/Resources/Wrap.txt index 38ddc23d5..06a6104c2 100644 --- a/Resources/Wrap.txt +++ b/Resources/Wrap.txt @@ -27,7 +27,6 @@ 0805A000 090B2000 0805B000 090B3000 0900D000 0900F000 -09012000 09047000 09063000 09026000 09068000 09026000 090E3000 2E006000 From 6f94ab8c52fda8d903d82aab11c3b5b5e8bb23df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 18 Jan 2025 22:36:37 +0100 Subject: [PATCH 30/57] Add TMVehicle.Gbx support for CGameItemModel --- .../Engines/GameData/CGameItemModel.chunkl | 32 ++++++++++++++++--- .../Engines/Plug/CPlugAudioEnvironment.chunkl | 31 ++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl b/Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl index 0e3217165..88af566b2 100644 --- a/Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl +++ b/Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl @@ -7,23 +7,47 @@ CGameItemModel 0x2E002000 0x001 (header, struct: SHeaderFileVersion) // file version version +0x000 + CSceneMobil Vehicle (external) + +0x003 + CMwNod + 0x006 int 0x008 // Nadeo skin fids - CMwNod?[] NadeoSkinFids + CMwNod?[] NadeoSkinFids (external) 0x009 // cameras - CMwNod[]_deprec Cameras + CMwNod[]_deprec Cameras (external) 0x00A + CPlugDecoratorSolid DecoratorSolid (external) + +0x00B + CMwNod CMwNod 0x00C // race interface fid CMwNod RaceInterfaceFid +0x00D + CMwNod[] + 0x010 - CMwNod + CPlugBitmap BannerProfileFid (external) + +0x011 + CPlugMaterial MaterialSkin (external) + CPlugMaterial MaterialGlass (external) + CPlugMaterial MaterialDetails (external) + CPlugMaterial MaterialPilot (external) + CPlugLight FrontLight (external) + CPlugLight FrontLightSmall (external) + CPlugLight RearLight (external) + CPlugLight ProjShadow (external) + CPlugLight ProjFront (external) 0x012 vec3 GroundPoint @@ -33,7 +57,7 @@ CGameItemModel 0x2E002000 float OrbitalPreviewAngle 0x013 - CPlugAudioEnvironment + CPlugAudioEnvironment AudioEnvironmentInCar (external) 0x014 CMwNod diff --git a/Src/GBX.NET/Engines/Plug/CPlugAudioEnvironment.chunkl b/Src/GBX.NET/Engines/Plug/CPlugAudioEnvironment.chunkl index 19f5e9d62..25d8413b3 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugAudioEnvironment.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugAudioEnvironment.chunkl @@ -1,5 +1,36 @@ CPlugAudioEnvironment 0x09039000 - inherits: CPlugAudio +0x000 + int + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + bool + bool + bool + bool + bool + bool + bool + bool + 0x001 float \ No newline at end of file From 2bbf9e5e9e6a9c8cd57393fa2a3a71098f3dd5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sat, 18 Jan 2025 22:37:13 +0100 Subject: [PATCH 31/57] Various classic and chunk fixes --- .../Engines/Function/CFuncLight.chunkl | 11 +++- .../Engines/Function/CFuncLightColor.chunkl | 10 ++++ .../Function/CFuncShaderLayerUV.chunkl | 10 ++++ .../Function/CFuncTreeTranslate.chunkl | 9 ++++ Src/GBX.NET/Engines/Graphic/GxFog.chunkl | 15 +++++- .../Motion/CMotionTrackMobilPitchin.chunkl | 12 +++++ Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl | 2 +- Src/GBX.NET/Engines/Plug/CPlugFileGPU.chunkl | 3 ++ Src/GBX.NET/Engines/Plug/CPlugFileGPUP.chunkl | 3 ++ Src/GBX.NET/Engines/Plug/CPlugFileGPUV.chunkl | 3 ++ Src/GBX.NET/Engines/Plug/CPlugFileGen.chunkl | 2 + Src/GBX.NET/Engines/Plug/CPlugFilePsh.chunkl | 2 + Src/GBX.NET/Engines/Plug/CPlugFileText.chunkl | 2 + .../Engines/Plug/CPlugFileVHlsl.chunkl | 2 + Src/GBX.NET/Engines/Plug/CPlugSound.chunkl | 50 ++++++++++++++++++- Src/GBX.NET/Engines/Scene/CSceneFx.chunkl | 2 + Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl | 9 +++- Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl | 2 + .../VirtualSkipper/CVskCollection.chunkl | 12 +++++ 19 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 Src/GBX.NET/Engines/Function/CFuncLightColor.chunkl create mode 100644 Src/GBX.NET/Engines/Function/CFuncTreeTranslate.chunkl create mode 100644 Src/GBX.NET/Engines/Motion/CMotionTrackMobilPitchin.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugFileGPU.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugFileGPUP.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugFileGPUV.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugFileGen.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugFilePsh.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugFileText.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugFileVHlsl.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CSceneFx.chunkl create mode 100644 Src/GBX.NET/Engines/VirtualSkipper/CVskCollection.chunkl diff --git a/Src/GBX.NET/Engines/Function/CFuncLight.chunkl b/Src/GBX.NET/Engines/Function/CFuncLight.chunkl index e65178a82..477907fb4 100644 --- a/Src/GBX.NET/Engines/Function/CFuncLight.chunkl +++ b/Src/GBX.NET/Engines/Function/CFuncLight.chunkl @@ -1,3 +1,12 @@ CFuncLight 0x05018000 - inherits: CFuncPlug -- abstract \ No newline at end of file +- abstract + +0x000 + int FctType + float FlickPeriod + int FlickCount + +enum EFctType + Sinus + Flick \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Function/CFuncLightColor.chunkl b/Src/GBX.NET/Engines/Function/CFuncLightColor.chunkl new file mode 100644 index 000000000..0004c0dc8 --- /dev/null +++ b/Src/GBX.NET/Engines/Function/CFuncLightColor.chunkl @@ -0,0 +1,10 @@ +CFuncLightColor 0x05019000 +- inherits: CFuncLight + +0x001 + vec4 Color0 + vec4 Color1 + +0x002 (base: 0x001) + base + CPlugFileImg Image (external) \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl b/Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl index 17f978898..a5e2fc662 100644 --- a/Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl +++ b/Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl @@ -18,10 +18,20 @@ CFuncShaderLayerUV 0x05015000 vec2 vec2 +0x011 + int + int + bool + bool + bool + CMwNod + 0x012 int int +0x013 (base: 0x00A) + 0x014 float float diff --git a/Src/GBX.NET/Engines/Function/CFuncTreeTranslate.chunkl b/Src/GBX.NET/Engines/Function/CFuncTreeTranslate.chunkl new file mode 100644 index 000000000..4f74e606b --- /dev/null +++ b/Src/GBX.NET/Engines/Function/CFuncTreeTranslate.chunkl @@ -0,0 +1,9 @@ +CFuncTreeTranslate 0x0500D000 +- inherits: CFuncTree + +0x000 + vec3 StartPoint + vec3 EndPoint + +0x001 + uint \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Graphic/GxFog.chunkl b/Src/GBX.NET/Engines/Graphic/GxFog.chunkl index ffb0d6a25..612f689a6 100644 --- a/Src/GBX.NET/Engines/Graphic/GxFog.chunkl +++ b/Src/GBX.NET/Engines/Graphic/GxFog.chunkl @@ -1 +1,14 @@ -GxFog 0x04004000 \ No newline at end of file +GxFog 0x04004000 + +0x000 + bool + int + float + float + float + float + float + float + float + float + float \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Motion/CMotionTrackMobilPitchin.chunkl b/Src/GBX.NET/Engines/Motion/CMotionTrackMobilPitchin.chunkl new file mode 100644 index 000000000..bff62c795 --- /dev/null +++ b/Src/GBX.NET/Engines/Motion/CMotionTrackMobilPitchin.chunkl @@ -0,0 +1,12 @@ +CMotionTrackMobilPitchin 0x08041000 +- inherits: CMotionTrack + +0x002 + CMwNod + float + float + float + float + int + float + float \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl b/Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl index 49043229b..1ff188cb9 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl @@ -1,9 +1,9 @@ CPlugClouds 0x09180000 0x000 + CMwNod[] float BottomNearZ float BottomFarZ - float CPlugFileImg ImageColorMin (external) CPlugFileImg ImageColorMax (external) int Lighting diff --git a/Src/GBX.NET/Engines/Plug/CPlugFileGPU.chunkl b/Src/GBX.NET/Engines/Plug/CPlugFileGPU.chunkl new file mode 100644 index 000000000..9c2d0eae7 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugFileGPU.chunkl @@ -0,0 +1,3 @@ +CPlugFileGPU 0x09040000 +- inherits: CPlugFileText +- abstract \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugFileGPUP.chunkl b/Src/GBX.NET/Engines/Plug/CPlugFileGPUP.chunkl new file mode 100644 index 000000000..0c704b283 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugFileGPUP.chunkl @@ -0,0 +1,3 @@ +CPlugFileGPUP 0x09076000 +- inherits: CPlugFileGPU +- abstract \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugFileGPUV.chunkl b/Src/GBX.NET/Engines/Plug/CPlugFileGPUV.chunkl new file mode 100644 index 000000000..dff591676 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugFileGPUV.chunkl @@ -0,0 +1,3 @@ +CPlugFileGPUV 0x09075000 +- inherits: CPlugFileGPU +- abstract \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugFileGen.chunkl b/Src/GBX.NET/Engines/Plug/CPlugFileGen.chunkl new file mode 100644 index 000000000..03602bc86 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugFileGen.chunkl @@ -0,0 +1,2 @@ +CPlugFileGen 0x0902F000 +- inherits: CPlugFileImg \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugFilePsh.chunkl b/Src/GBX.NET/Engines/Plug/CPlugFilePsh.chunkl new file mode 100644 index 000000000..ab81b523b --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugFilePsh.chunkl @@ -0,0 +1,2 @@ +CPlugFilePsh 0x09045000 +- inherits: CPlugFileGPUP \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugFileText.chunkl b/Src/GBX.NET/Engines/Plug/CPlugFileText.chunkl new file mode 100644 index 000000000..e0988db42 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugFileText.chunkl @@ -0,0 +1,2 @@ +CPlugFileText 0x09041000 +- inherits: CPlugFile \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugFileVHlsl.chunkl b/Src/GBX.NET/Engines/Plug/CPlugFileVHlsl.chunkl new file mode 100644 index 000000000..9af9f45a2 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugFileVHlsl.chunkl @@ -0,0 +1,2 @@ +CPlugFileVHlsl 0x09074000 +- inherits: CPlugFileGPUV \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugSound.chunkl b/Src/GBX.NET/Engines/Plug/CPlugSound.chunkl index 85c7f0e4f..4df110762 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugSound.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugSound.chunkl @@ -2,4 +2,52 @@ CPlugSound 0x0901A000 - inherits: CPlugAudio 0x000 - CMwNod (external) \ No newline at end of file + CMwNod PlugFile (external) // CPlugFileSnd + +0x002 + id + +0x009 + int Mode + float + bool IsLooping + bool IsContinuous + float Priority + +0x00B + int SoundKind + int InsideConeANgle + int OutsideConeAngle + float ConeOutsideAttenuation + float + +0x00C + float RefDistance + float MaxDistance + bool EnableDoppler + float + float + float + float + float DopplerFactor + float RolloffFactor + float RoomRolloffFactor + float AirAbsorptionFactor + +0x00D + int Mode + float + bool IsLooping + bool IsContinuous + float Priority + +enum ESoundKind + Point + Directional + +enum EMode + Direct + Direct_w__attenuation + Spatialised + Spacialised_Omni + ForceHard3d \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneFx.chunkl b/Src/GBX.NET/Engines/Scene/CSceneFx.chunkl new file mode 100644 index 000000000..3bd2f0371 --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneFx.chunkl @@ -0,0 +1,2 @@ +CSceneFx 0x0A072000 +- abstract \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl b/Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl index 95c9012be..0a2877e46 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneFxNod.chunkl @@ -1 +1,8 @@ -CSceneFxNod 0x0A03A000 \ No newline at end of file +CSceneFxNod 0x0A03A000 + +0x000 + CSceneFx Fx + +0x001 + CSceneFxNod[]_deprec NodInputs + int \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl index b02f86831..839e1c7ab 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl @@ -14,6 +14,8 @@ CSceneLayout 0x0A003000 box iso4 +0x017 (ignore) + 0x018 CSceneSector[]_deprec Sectors version diff --git a/Src/GBX.NET/Engines/VirtualSkipper/CVskCollection.chunkl b/Src/GBX.NET/Engines/VirtualSkipper/CVskCollection.chunkl new file mode 100644 index 000000000..8f98a63ee --- /dev/null +++ b/Src/GBX.NET/Engines/VirtualSkipper/CVskCollection.chunkl @@ -0,0 +1,12 @@ +CVskCollection 0x21085000 +- inherits: CGameCtnCollection + +0x000 + CMwNod + CMwNod + +0x001 + float + float + float + float \ No newline at end of file From 930f83ef37ff1278bff1a9b6f8fba5186b7e8711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 19 Jan 2025 03:00:15 +0100 Subject: [PATCH 32/57] Add VehicleStruct support --- .../Engines/Function/CFuncLight.chunkl | 2 +- .../Plug/CPlugVehicleMaterialGroup.chunkl | 4 + .../Plug/CPlugVehicleVisEmitterModel.chunkl | 42 ++++++ .../Plug/CPlugVehicleVisModelShared.chunkl | 54 +++++++ .../Plug/CPlugVehicleVisModelShared.cs | 132 ++++++++++++++++++ .../Engines/Scene/CSceneVehicle.chunkl | 9 +- .../Engines/Scene/CSceneVehicleCar.chunkl | 7 +- .../Scene/CSceneVehicleEnvironment.chunkl | 7 + 8 files changed, 254 insertions(+), 3 deletions(-) create mode 100644 Src/GBX.NET/Engines/Plug/CPlugVehicleMaterialGroup.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugVehicleVisEmitterModel.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl create mode 100644 Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs create mode 100644 Src/GBX.NET/Engines/Scene/CSceneVehicleEnvironment.chunkl diff --git a/Src/GBX.NET/Engines/Function/CFuncLight.chunkl b/Src/GBX.NET/Engines/Function/CFuncLight.chunkl index 477907fb4..890e9a6eb 100644 --- a/Src/GBX.NET/Engines/Function/CFuncLight.chunkl +++ b/Src/GBX.NET/Engines/Function/CFuncLight.chunkl @@ -3,7 +3,7 @@ CFuncLight 0x05018000 - abstract 0x000 - int FctType + int FctType float FlickPeriod int FlickCount diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleMaterialGroup.chunkl b/Src/GBX.NET/Engines/Plug/CPlugVehicleMaterialGroup.chunkl new file mode 100644 index 000000000..120f31869 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleMaterialGroup.chunkl @@ -0,0 +1,4 @@ +CPlugVehicleMaterialGroup 0x090E9000 + +0x000 + int[] \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisEmitterModel.chunkl b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisEmitterModel.chunkl new file mode 100644 index 000000000..1e8ea673f --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisEmitterModel.chunkl @@ -0,0 +1,42 @@ +CPlugVehicleVisEmitterModel 0x090E6000 + +0x002 + bool + +0x003 + float + float + float + float + float + float + +0x004 + int + CPlugParticleEmitterModel (external) + CPlugParticleEmitterModel (external) + CPlugParticleEmitterModel (external) + int + int + int + bool + bool + bool + iso4 + float + float + float + float + float + float + float + float + float + float + float + float + float + float + +0x005 + bool \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl new file mode 100644 index 000000000..24a00219f --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl @@ -0,0 +1,54 @@ +CPlugVehicleVisModelShared 0x090E8000 + +0x005 + SimulationWheel[] SimulationWheels + +0x006 + +0x009 + +0x00A + +0x00F + +0x010 + +0x012 + CPlugVehicleMaterialGroup[]_deprec VehicleMaterialGroups + +0x013 + CFuncKeysReal + CFuncKeysReal + CFuncKeysReal + +0x014 + CPlugVehicleVisEmitterModel[]_deprec VehicleEmitters + +archive SimulationWheel + bool + bool + id Name + +archive VisualArm + VisualId + VisualId + VisualId + bool + bool + int + +archive VisualLight + VisualId + bool + +archive VisualWheel + VisualId + VisualId + VisualId + VisualId + int + bool + +archive VisualId + id + bool \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs new file mode 100644 index 000000000..43360ad55 --- /dev/null +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs @@ -0,0 +1,132 @@ + +namespace GBX.NET.Engines.Plug; + +public partial class CPlugVehicleVisModelShared +{ + public VisualVehicle[] VisualVehicles { get; set; } = []; + + public partial class Chunk090E8006 + { + public override void Read(CPlugVehicleVisModelShared n, GbxReader r) + { + n.VisualVehicles = new VisualVehicle[r.ReadInt32()]; + } + + public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) + { + w.Write(n.VisualVehicles.Length); + } + } + + public partial class Chunk090E8009 + { + public override void Read(CPlugVehicleVisModelShared n, GbxReader r) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + n.VisualVehicles[i] ??= new VisualVehicle(); + n.VisualVehicles[i].VisualArms = r.ReadArrayReadable(); + } + } + + public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + w.WriteArrayWritable(n.VisualVehicles[i].VisualArms); + } + } + } + + public partial class Chunk090E800A + { + public override void Read(CPlugVehicleVisModelShared n, GbxReader r) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + n.VisualVehicles[i] ??= new VisualVehicle(); + n.VisualVehicles[i].VisualLights = r.ReadArrayReadable(); + } + } + + public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + w.WriteArrayWritable(n.VisualVehicles[i].VisualLights); + } + } + } + + public partial class Chunk090E800F + { + public override void Read(CPlugVehicleVisModelShared n, GbxReader r) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + n.VisualVehicles[i] ??= new VisualVehicle(); + n.VisualVehicles[i].VisualWheels = r.ReadArrayReadable(); + } + } + + public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + w.WriteArrayWritable(n.VisualVehicles[i].VisualWheels); + } + } + } + + public partial class Chunk090E8010 + { + public override void Read(CPlugVehicleVisModelShared n, GbxReader r) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + n.VisualVehicles[i] ??= new VisualVehicle(); + n.VisualVehicles[i].U01 = r.ReadReadable(); + n.VisualVehicles[i].U02 = r.ReadReadable(); + n.VisualVehicles[i].U03 = r.ReadReadable(); + n.VisualVehicles[i].U04 = r.ReadReadable(); + n.VisualVehicles[i].U05 = r.ReadInt32(); + } + } + + public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + w.WriteWritable(n.VisualVehicles[i].U01); + w.WriteWritable(n.VisualVehicles[i].U02); + w.WriteWritable(n.VisualVehicles[i].U03); + w.WriteWritable(n.VisualVehicles[i].U04); + w.Write(n.VisualVehicles[i].U05); + } + } + } + + [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] + public partial class VisualId; + + [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] + public partial class VisualArm; + + [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] + public partial class VisualLight; + + [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] + public partial class VisualWheel; + + public sealed class VisualVehicle + { + public VisualArm[] VisualArms { get; set; } = []; + public VisualLight[] VisualLights { get; set; } = []; + public VisualWheel[] VisualWheels { get; set; } = []; + public VisualId? U01 { get; set; } + public VisualId? U02 { get; set; } + public VisualId? U03 { get; set; } + public VisualId? U04 { get; set; } + public int U05 { get; set; } + } +} diff --git a/Src/GBX.NET/Engines/Scene/CSceneVehicle.chunkl b/Src/GBX.NET/Engines/Scene/CSceneVehicle.chunkl index bc17043c2..d148198fa 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneVehicle.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneVehicle.chunkl @@ -1,2 +1,9 @@ CSceneVehicle 0x0A060000 -- inherits: CSceneMobil \ No newline at end of file +- inherits: CSceneMobil + +0x000 + CPlugVehiclePhyTunings VehicleTunings (external) + CMwRefBuffer VehicleMaterials (external) + CSceneVehicleEnvironment Environment + CMwNod + CPlugVehicleVisModelShared VehicleStruct (external) \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneVehicleCar.chunkl b/Src/GBX.NET/Engines/Scene/CSceneVehicleCar.chunkl index e7c79c472..ed12a745f 100644 --- a/Src/GBX.NET/Engines/Scene/CSceneVehicleCar.chunkl +++ b/Src/GBX.NET/Engines/Scene/CSceneVehicleCar.chunkl @@ -1,2 +1,7 @@ CSceneVehicleCar 0x0A02B000 -- inherits: CSceneVehicle \ No newline at end of file +- inherits: CSceneVehicle + +0x00C + float + float + box \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneVehicleEnvironment.chunkl b/Src/GBX.NET/Engines/Scene/CSceneVehicleEnvironment.chunkl new file mode 100644 index 000000000..9a27c5c70 --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneVehicleEnvironment.chunkl @@ -0,0 +1,7 @@ +CSceneVehicleEnvironment 0x0A033000 + +0x000 + bool + +0x002 + CPlugMaterial[] Materials (external) \ No newline at end of file From 70ae83315dee643281c22bb9bafde15775a704c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 19 Jan 2025 03:10:48 +0100 Subject: [PATCH 33/57] Cleaner visualization --- .../Plug/CPlugVehicleVisModelShared.chunkl | 2 +- .../Plug/CPlugVehicleVisModelShared.cs | 43 ++++++++++++++++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl index 24a00219f..b78ebf7fb 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl @@ -50,5 +50,5 @@ archive VisualWheel bool archive VisualId - id + id Name bool \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs index 43360ad55..a79adeade 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs @@ -1,5 +1,4 @@ - -namespace GBX.NET.Engines.Plug; +namespace GBX.NET.Engines.Plug; public partial class CPlugVehicleVisModelShared { @@ -106,17 +105,49 @@ public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) } } + public partial class SimulationWheel + { + public override string ToString() + { + return $"{Name} (U01: {U01}, U02: {U01})"; + } + } + [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] - public partial class VisualId; + public partial class VisualId + { + public override string ToString() + { + return $"{Name} (U01: {U01})"; + } + } [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] - public partial class VisualArm; + public partial class VisualArm + { + public override string ToString() + { + return $"{U01}, {U02}, {U03} [U04: {U04}, U05: {U05}, U06: {U06}]"; + } + } [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] - public partial class VisualLight; + public partial class VisualLight + { + public override string ToString() + { + return $"{U01} [U02: {U02}]"; + } + } [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] - public partial class VisualWheel; + public partial class VisualWheel + { + public override string ToString() + { + return $"{U01}, {U02}, {U03}, {U04} [U05: {U05}, U06: {U06}]"; + } + } public sealed class VisualVehicle { From 6b1a03637803be51bc65b18cdea8dbfe2e66cfb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 19 Jan 2025 03:31:14 +0100 Subject: [PATCH 34/57] Make CPlugVehiclePhyTuning.Name not nullable --- Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.chunkl | 2 +- Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.chunkl b/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.chunkl index 8e302726b..164e9140b 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.chunkl @@ -1,7 +1,7 @@ CPlugVehiclePhyTuning 0x090EB000 0x000 - id Name + id Name = empty CFuncKeysReal float diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs b/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs index 3d0b00f20..2ca8ef5a3 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs +++ b/Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTuning.cs @@ -23,4 +23,9 @@ public override void ReadWrite(CPlugVehiclePhyTuning n, GbxReaderWriter rw) } } } + + public override string ToString() + { + return Name; + } } From 878fbece88ff3717649cdf0bf91cbe65f0983a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Sun, 19 Jan 2025 03:40:40 +0100 Subject: [PATCH 35/57] Update to 2.1.1 --- Src/GBX.NET/GBX.NET.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/GBX.NET/GBX.NET.csproj b/Src/GBX.NET/GBX.NET.csproj index 1e79e7a15..f512939d0 100644 --- a/Src/GBX.NET/GBX.NET.csproj +++ b/Src/GBX.NET/GBX.NET.csproj @@ -2,7 +2,7 @@ GBX.NET - 2.1.0 + 2.1.1 BigBang1112 General purpose library for Gbx files - data from Nadeo games like Trackmania or Shootmania. It supports high performance serialization and deserialization of 200+ Gbx classes. Copyright (c) 2024 Petr Pivoňka From bef6f7d0d3b6c2250cc9c270d062ebf96b5182fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 18:57:43 +0100 Subject: [PATCH 36/57] Add CGameControlCameras --- .../Engines/Game/CGameControlCamera.chunkl | 35 +++++++++ .../Game/CGameControlCameraTarget.chunkl | 11 +++ .../Engines/Scene/CSceneController.chunkl | 1 + .../CGameControlCameraTrackManiaRace.chunkl | 18 +++++ .../CGameControlCameraTrackManiaRace2.chunkl | 69 +++++++++++++++++ .../CGameControlCameraTrackManiaRace3.chunkl | 75 +++++++++++++++++++ 6 files changed, 209 insertions(+) create mode 100644 Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl create mode 100644 Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl create mode 100644 Src/GBX.NET/Engines/Scene/CSceneController.chunkl create mode 100644 Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl create mode 100644 Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl create mode 100644 Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl diff --git a/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl b/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl new file mode 100644 index 000000000..1ecb67daa --- /dev/null +++ b/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl @@ -0,0 +1,35 @@ +CGameControlCamera 0x0306B000 +- inherits: CSceneController + +0x00A + id Name + +0x00B + float + float + float + bool + bool + bool + float + float + float + float + float + float + bool + iso4 + bool + float + float + bool + float + float + float + float + float + float + float + float + float + bool \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl b/Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl new file mode 100644 index 000000000..9e87b1b95 --- /dev/null +++ b/Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl @@ -0,0 +1,11 @@ +CGameControlCameraTarget 0x03072000 +- inherits: CGameControlCamera + +0x001 + iso4 + bool + bool + float + +0x002 + bool \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Scene/CSceneController.chunkl b/Src/GBX.NET/Engines/Scene/CSceneController.chunkl new file mode 100644 index 000000000..1e533d54a --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CSceneController.chunkl @@ -0,0 +1 @@ +CSceneController 0x0A00C000 \ No newline at end of file diff --git a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl new file mode 100644 index 000000000..2bc29a1d3 --- /dev/null +++ b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl @@ -0,0 +1,18 @@ +CGameControlCameraTrackManiaRace 0x24085000 +- inherits: CGameControlCameraTarget + +0x000 + float + float + float + bool + float + float + float + float + bool + float + float + float + float + float \ No newline at end of file diff --git a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl new file mode 100644 index 000000000..14250f8b1 --- /dev/null +++ b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl @@ -0,0 +1,69 @@ +CGameControlCameraTrackManiaRace2 0x24086000 +- inherits: CGameControlCameraTarget + +0x000 + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + float + int + int + int + int + int + int + float + float + CFuncKeysReal + CFuncKeysReal + CFuncKeysReal + float + float + float + float + +0x001 + bool \ No newline at end of file diff --git a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl new file mode 100644 index 000000000..b76eab2a6 --- /dev/null +++ b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl @@ -0,0 +1,75 @@ +CGameControlCameraTrackManiaRace3 0x24087000 +- inherits: CGameControlCameraTarget + +0x000 + float + float + float + int + int + int + float + float + float + int + int + float + int + int + float + int + int + float + int + int + float + float + int + int + float + float + float + int + int + float + int + int + float + float + int + int + float + float + float + float + float + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + float + int + int + CFuncKeysReal + CFuncKeysReal + CFuncKeysReal + +0x001 + float \ No newline at end of file From ba7c37d2017c9baa323af1b241243a0257aacb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 20:54:42 +0100 Subject: [PATCH 37/57] Change log level to Info on header class ID --- Src/GBX.NET/Serialization/GbxHeaderReader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/GBX.NET/Serialization/GbxHeaderReader.cs b/Src/GBX.NET/Serialization/GbxHeaderReader.cs index 83c6480f5..46ccfc018 100644 --- a/Src/GBX.NET/Serialization/GbxHeaderReader.cs +++ b/Src/GBX.NET/Serialization/GbxHeaderReader.cs @@ -95,11 +95,11 @@ private uint ReadClassId() if (rawClassId == classId) { - logger?.LogDebug("Class ID: 0x{ClassId:X8} ({ClassName})", classId, ClassManager.GetName(classId) ?? "unknown class"); + logger?.LogInformation("Class ID: 0x{ClassId:X8} ({ClassName})", classId, ClassManager.GetName(classId) ?? "unknown class"); } else { - logger?.LogDebug("Class ID: 0x{ClassId:X8} (raw: 0x{RawClassId:X8}, {RawClassName} -> {ClassName})", + logger?.LogInformation("Class ID: 0x{ClassId:X8} (raw: 0x{RawClassId:X8}, {RawClassName} -> {ClassName})", classId, rawClassId, ClassManager.GetName(rawClassId) ?? "unknown class", ClassManager.GetName(classId) ?? "unknown class"); From 3d350a57219fb07b615e59dda51c46e81fb00108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 20:55:18 +0100 Subject: [PATCH 38/57] Add Unlimiter class names (custom-made) --- .../ClassChunkLMixedGenerator.cs | 2 +- Resources/ClassIdManual.txt | Bin 0 -> 168 bytes Src/GBX.NET/GBX.NET.csproj | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 Resources/ClassIdManual.txt diff --git a/Generators/GBX.NET.Generators/ClassChunkLMixedGenerator.cs b/Generators/GBX.NET.Generators/ClassChunkLMixedGenerator.cs index 8ae9cd0bf..bce4d30da 100644 --- a/Generators/GBX.NET.Generators/ClassChunkLMixedGenerator.cs +++ b/Generators/GBX.NET.Generators/ClassChunkLMixedGenerator.cs @@ -230,7 +230,7 @@ public virtual void Initialize(IncrementalGeneratorInitializationContext context var classIdContents = context.AdditionalTextsProvider .Where(static file => { - return file.Path.EndsWith("ClassId.txt") && Path.GetDirectoryName(file.Path).EndsWith("Resources"); + return (file.Path.EndsWith("ClassId.txt") || file.Path.EndsWith("ClassIdManual.txt")) && Path.GetDirectoryName(file.Path).EndsWith("Resources"); }) .Select((additionalText, cancellationToken) => { diff --git a/Resources/ClassIdManual.txt b/Resources/ClassIdManual.txt new file mode 100644 index 0000000000000000000000000000000000000000..4e0cdf6762024adad9870e87ffaf4ffb01953574 GIT binary patch literal 168 zcmezW&zQlDL4hHZA&()4A(J5&h)Wn!8HyNq8MuJr20&;Cq@5Yu84`iAsX$fDvD;6_?fVv8RCL}UcGJx304EaENQ?Qx@03(7PcmMzZ literal 0 HcmV?d00001 diff --git a/Src/GBX.NET/GBX.NET.csproj b/Src/GBX.NET/GBX.NET.csproj index f512939d0..3984b02a7 100644 --- a/Src/GBX.NET/GBX.NET.csproj +++ b/Src/GBX.NET/GBX.NET.csproj @@ -89,6 +89,7 @@ + From 4394443a3a2c1960946892746195e432ffcf27b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 20:57:36 +0100 Subject: [PATCH 39/57] Explorer: full chunk ID, fixes to missing names --- .../Client/Components/ChunkViewer.razor | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Tools/GbxExplorerOld/Client/Components/ChunkViewer.razor b/Tools/GbxExplorerOld/Client/Components/ChunkViewer.razor index 8de1cf3bf..f334887f6 100644 --- a/Tools/GbxExplorerOld/Client/Components/ChunkViewer.razor +++ b/Tools/GbxExplorerOld/Client/Components/ChunkViewer.razor @@ -36,15 +36,14 @@ } } - var chunkId = Chunk.Id & 0xFFF; var isSameBaseId = true; }
+ @onclick="async () => await OpenOrCloseChunkAsync(chunkType)" + @onmouseover="() => over = true" + @onmouseout="() => over = false"> @if (chunkType.IsGenericType) { @@ -54,7 +53,7 @@ if (classId.HasValue && (classId.Value & 0xFFFFF000) == (Chunk.Id & 0xFFFFF000)) { - @name + @name } else { @@ -65,12 +64,17 @@ } else { - @chunkType.DeclaringType?.Name + var className = chunkType.DeclaringType?.Name ?? GBX.NET.Managers.ClassManager.GetName(Chunk.Id & 0xFFFFF000); + + if (!string.IsNullOrEmpty(className)) + { + @className + } } @if (isSameBaseId) { - 0x@(chunkId.ToString("X3") ?? "XXX") + 0x@(Chunk.Id.ToString("X8")) } @if (Chunk is IVersionable chunkVersionable) @@ -80,7 +84,7 @@ @if (!string.IsNullOrWhiteSpace(atts?.Description)) { - (@atts.Description) + (@atts.Description) } @if (atts is null) From f2e40e59d351706290b623772e9f60aea456cc4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 20:58:00 +0100 Subject: [PATCH 40/57] Explorer: Add namespace on grouping hover --- Tools/GbxExplorerOld/Client/Components/NodeTree.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/GbxExplorerOld/Client/Components/NodeTree.razor b/Tools/GbxExplorerOld/Client/Components/NodeTree.razor index d829cbae6..de6c043f3 100644 --- a/Tools/GbxExplorerOld/Client/Components/NodeTree.razor +++ b/Tools/GbxExplorerOld/Client/Components/NodeTree.razor @@ -50,7 +50,7 @@ if (declaringTypeGroups.Count > 1) { -
  • +
  • @(sameDeclaringTypes || group.Key?.DeclaringType is null ? "" : $"{group.Key.DeclaringType.Name}.")@group.Key?.Name
  • } From 9ae459b3eed544b1328481c540159ab250e6a1aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 22:09:35 +0100 Subject: [PATCH 41/57] Add loads of tmf camera stuff --- .../Engines/Game/CGameControlCamera.chunkl | 50 +++---- .../Game/CGameControlCameraTarget.chunkl | 10 +- .../CGameControlCameraTrackManiaRace.chunkl | 22 +-- .../CGameControlCameraTrackManiaRace2.chunkl | 126 ++++++++-------- .../CGameControlCameraTrackManiaRace3.chunkl | 136 +++++++++--------- 5 files changed, 170 insertions(+), 174 deletions(-) diff --git a/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl b/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl index 1ecb67daa..f9f6b8fe7 100644 --- a/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl @@ -5,31 +5,27 @@ CGameControlCamera 0x0306B000 id Name 0x00B - float - float - float - bool - bool - bool - float - float - float - float - float - float - bool - iso4 - bool - float - float - bool - float - float - float - float - float - float - float - float - float + vec3 RelativeFollowedPos + bool IsFirstPerson + bool CanCameraMove + bool IsFollowing + float MaxSpeed + float PlaneDist + float MinDist + float MaxDist + float Fov + float DefaultFov + bool UseForcedLocation + iso4 ForcedLocation + bool UseOnlyFollowedMobilPosition + float MinFov + float MaxFov + bool UseForcedUp + vec3 ForcedUp + float DefaultNearZ + float MinNearZ + float MaxNearZ + float DefaultFarZ + float MinFarZ + float MaxFarZ bool \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl b/Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl index 9e87b1b95..079950c6c 100644 --- a/Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl @@ -2,10 +2,10 @@ CGameControlCameraTarget 0x03072000 - inherits: CGameControlCamera 0x001 - iso4 - bool - bool - float + iso4 Location + bool IsUpLinked + bool Interpolate + float LookAtFactor 0x002 - bool \ No newline at end of file + bool CanUseRelativeTargetLocation \ No newline at end of file diff --git a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl index 2bc29a1d3..e52d55701 100644 --- a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl +++ b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl @@ -2,17 +2,17 @@ CGameControlCameraTrackManiaRace 0x24085000 - inherits: CGameControlCameraTarget 0x000 - float - float - float - bool - float - float - float - float - bool - float - float + float ConeAperture + float ConeMinSpeed + float ConeMaxSpeed + bool UseSpeedDir + float CarCameraHeight + float CarCameraDistance + float CarCameraTargetDistance + float CarCameraAlign + bool IsSegmentCast + float SegmentCastMinDist + float SegmentCastLength float float float \ No newline at end of file diff --git a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl index 14250f8b1..3232f8c73 100644 --- a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl +++ b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl @@ -2,68 +2,68 @@ CGameControlCameraTrackManiaRace2 0x24086000 - inherits: CGameControlCameraTarget 0x000 - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - float - int - int - int - int - int - int - float - float - CFuncKeysReal - CFuncKeysReal - CFuncKeysReal - float - float - float - float + float InputGasDistDelta + int InputGasDistTimeUp + int InputGasDistTimeDown + float InputBrakeDistDelta + int InputBrakeDistTimeUp + int InputBrakeDistTimeDown + float InputSteerDistDelta + int InputSteerDistTimeUp + int InputSteerDistTimeDown + float EventTurboFovDelta + int EventTurboFovTimeUp + int EventTurboFovTimeDown + float EventTurboDistDelta + int EventTurboDistTimeUp + int EventTurboDistTimeDown + float EventChangeGearDistDelta + int EventChangeGearDistTimeUp + int EventChangeGearDistTimeDown + float EventBurningLookAtFactorDelta + int EventBurningLookAtFactorTimeUp + int EventBurningLookAtFactorTimeDown + float EventBurningDistDelta + int EventBurningDistTimeUp + int EventBurningDistTimeDown + float StateFlyingDistDelta + int StateFlyingDistTimeUp + int StateFlyingDistTimeDown + float StateFlyingPlaneDistDelta + int StateFlyingPlaneDistTimeUp + int StateFlyingPlaneDistTimeDown + float StateFlyingLookAtFactorDelta + int StateFlyingLookAtFactorTimeUp + int StateFlyingLookAtFactorTimeDown + float InputLeftSteerRollDelta + int InputLeftSteerRollTimeUp + int InputLeftSteerRollTimeDown + float InputRightSteerRollDelta + int InputRightSteerRollTimeUp + int InputRightSteerRollTimeDown + float InputLeftSteerYawDelta + int InputLeftSteerYawTimeUp + int InputLeftSteerYawTimeDown + float InputRightSteerYawDelta + int InputRightSteerYawTimeUp + int InputRightSteerYawTimeDown + float StateFlyingLookAtStep + float MinSpeed + int StateFlyingDurationBeforeFlyingMode + int StateFlyingDurationBeforeCameraMove + int InputSteerDurationBeforeBurnoutShowView + int InputSteerDurationBeforeAnticipatingTurnTriggered + int InputSteerDurationBeforeRollTriggered + int InputNoSteerDurationBeforeReset + float MaxDeltaPlaneDistStep + float MaxDeltaFovStep + CFuncKeysReal LookAtFactorFromUpSpeedRatio + CFuncKeysReal YawFromSpeed + CFuncKeysReal RollFromSpeed + float DeltaDistDamperKi + float DeltaDistDamperKa + float DeltaLookAtFactorDamperKi + float DeltaLookAtFactorDamperKa 0x001 - bool \ No newline at end of file + bool IsRollFromInput \ No newline at end of file diff --git a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl index b76eab2a6..f10bdd222 100644 --- a/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl +++ b/Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl @@ -2,74 +2,74 @@ CGameControlCameraTrackManiaRace3 0x24087000 - inherits: CGameControlCameraTarget 0x000 - float - float - float - int - int - int - float - float - float - int - int - float - int - int - float - int - int - float - int - int - float - float - int - int - float - float - float - int - int - float - int - int - float - float - int - int - float - float - float - float - float - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - float - int - int - CFuncKeysReal - CFuncKeysReal - CFuncKeysReal + float SlerpSpeed + float Up + float Far + int FlyDurationBeforeFlyingBehavior + int InputNoSteerDurationBeforeReset + int InputSteerDurationBeforeBurnoutShowView + float MinSpeed + float MinSpeed2 + float SlerpTargetPosNormalBehaviorDelta + int SlerpTargetPosNormalBehaviorTimeUp + int SlerpTargetPosNormalBehaviorTimeDown + float SlerpTargetPosFlyingDelta + int SlerpTargetPosFlyingTimeUp + int SlerpTargetPosFlyingTimeDown + float SlerpTargetPosDelta + int SlerpTargetPosTimeUp + int SlerpTargetPosTimeDown + float SlerpTargetCamUpDelta + int SlerpTargetCamUpTimeUp + int SlerpTargetCamUpTimeDown + float SlerpSpeedFlyingBehavior + float SlerpSpeedDelta + int SlerpSpeedTimeUp + int SlerpSpeedTimeDown + float SlerpSpeedCamUp + float SlerpSpeedCamUpFlyingBehavior + float SlerpSpeedCamUpDelta + int SlerpSpeedCamUpTimeUp + int SlerpSpeedCamUpTimeDown + float StateFlyingLookAtFactorDelta + int StateFlyingLookAtFactorTimeUp + int StateFlyingLookAtFactorTimeDown + float StateFlyingLookAtStep + float StateFlyingRadiusDelta + int StateFlyingRadiusTimeUp + int StateFlyingRadiusTimeDown + float ConstantFlyingLookDownFactor + float FlyingLookDownFactorKi + float FlyingLookDownFactorKa + float RadiusDamperKi + float RadiusDamperKa + float InputGasFarDelta + int InputGasFarTimeUp + int InputGasFarTimeDown + float InputBrakeFarDelta + int InputBrakeFarTimeUp + int InputBrakeFarTimeDown + float InputSteerFarDelta + int InputSteerFarTimeUp + int InputSteerFarTimeDown + float EventTurboFovDelta + int EventTurboFovTimeUp + int EventTurboFovTimeDown + float EventTurboFarDelta + int EventTurboFarTimeUp + int EventTurboFarTimeDown + float EventChangeGearFarDelta + int EventChangeGearFarTimeUp + int EventChangeGearFarTimeDown + float EventBurningLookAtFactorDelta + int + int EventBurningLookAtFactorTimeDown + float EventBurningRadiusDelta + int EventBurningRadiusTimeUp + int EventBurningRadiusTimeDown + CFuncKeysReal SlerpSpeedModulationFromSpeed + CFuncKeysReal LookAtFactorFromUpSpeedRatio + CFuncKeysReal FlyingLookDownFactorFromSpeedRatio 0x001 float \ No newline at end of file From 25a8c62e1806c87447da5b3994eaee9f70168843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 22:09:50 +0100 Subject: [PATCH 42/57] Add CGameCtnBlockInfo.Selection --- Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.chunkl | 7 ++++++- Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.cs | 14 +++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.chunkl index 2ff0a10dc..3612cb610 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.chunkl @@ -122,4 +122,9 @@ enum EMultiDir OpposedDirOnly PerpendicularDirsOnly NextDirOnly - PreviousDirOnly \ No newline at end of file + PreviousDirOnly + +enum ESelection + Random + Obsolete + AutoRotate \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.cs b/Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.cs index da2bec6e5..9d0a0f600 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.cs +++ b/Src/GBX.NET/Engines/Game/CGameCtnBlockInfo.cs @@ -4,10 +4,15 @@ namespace GBX.NET.Engines.Game; public partial class CGameCtnBlockInfo { + public ESelection Selection { get; set; } + private CGameCtnBlockInfoClassic? pillar; + [AppliedWithChunk] + public CGameCtnBlockInfoClassic? Pillar { get => pillarFile?.GetNode(ref pillar) ?? pillar; set => pillar = value; } private GbxRefTableFile? pillarFile; - public CGameCtnBlockInfoClassic? Pillar { get => pillar; set => pillar = value; } - + public GbxRefTableFile? PillarFile { get => pillarFile; set => pillarFile = value; } + public CGameCtnBlockInfoClassic? GetPillar(GbxReadSettings settings = default, bool exceptions = false) => pillarFile?.GetNode(ref pillar, settings, exceptions) ?? pillar; + private CGameCtnBlockUnitInfo[]? groundBlockUnitInfos; public CGameCtnBlockUnitInfo[]? GroundBlockUnitInfos { get => groundBlockUnitInfos; set => groundBlockUnitInfos = value; } @@ -38,7 +43,6 @@ public partial class Chunk0304E005 public int U02; public int U03; public int U04; - public int U05; public int U06; public byte U07; public int U08; @@ -53,7 +57,7 @@ public override void Read(CGameCtnBlockInfo n, GbxReader r) U03 = r.ReadInt32(); // always 0? U04 = r.ReadInt32(); // always 0? n.isPillar = r.ReadBoolean(); - U05 = r.ReadInt32(); // always 0? + n.Selection = (ESelection)r.ReadInt32(); U06 = r.ReadInt32(); // always 0? // @@ -88,7 +92,7 @@ public override void Write(CGameCtnBlockInfo n, GbxWriter w) w.Write(U03); w.Write(U04); w.Write(n.isPillar); - w.Write(U05); + w.Write((int)n.Selection); w.Write(U06); // From 720e2a4ea444d097477f1f5016f10d0538a2d853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 22:44:45 +0100 Subject: [PATCH 43/57] Add ParentCollectorId and IsInternal --- Src/GBX.NET/Engines/GameData/CGameCtnCollector.chunkl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/GBX.NET/Engines/GameData/CGameCtnCollector.chunkl b/Src/GBX.NET/Engines/GameData/CGameCtnCollector.chunkl index b853c68af..14a640c38 100644 --- a/Src/GBX.NET/Engines/GameData/CGameCtnCollector.chunkl +++ b/Src/GBX.NET/Engines/GameData/CGameCtnCollector.chunkl @@ -7,7 +7,7 @@ CGameCtnCollector 0x2E001000 // Collector. Something that can have an icon. v5= id v4+ - id + id ParentCollectorId v3+ int Flags short CatalogPosition @@ -32,7 +32,7 @@ CGameCtnCollector 0x2E001000 // Collector. Something that can have an icon. int 0x007 [TM10, TMSX, TMF] - bool + bool IsInternal bool int CatalogPosition int From ebecf007674e56019fa926127e20ab4762c5602e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 22:45:19 +0100 Subject: [PATCH 44/57] Add ParentCollectorId to body --- Src/GBX.NET/Engines/GameData/CGameCtnCollector.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Src/GBX.NET/Engines/GameData/CGameCtnCollector.cs b/Src/GBX.NET/Engines/GameData/CGameCtnCollector.cs index f612f4f1f..825f250ea 100644 --- a/Src/GBX.NET/Engines/GameData/CGameCtnCollector.cs +++ b/Src/GBX.NET/Engines/GameData/CGameCtnCollector.cs @@ -112,8 +112,6 @@ public override void Write(CGameCtnCollector n, GbxWriter w) public partial class Chunk2E001009 { - public string? U01; - public override void ReadWrite(CGameCtnCollector n, GbxReaderWriter rw) { rw.String(ref n.pageName); @@ -123,7 +121,7 @@ public override void ReadWrite(CGameCtnCollector n, GbxReaderWriter rw) rw.NodeRef(ref n.iconFid, ref n.iconFidFile); } - rw.Id(ref U01); + rw.Id(ref n.parentCollectorId); } } From a7f7a16ad9c4df51aa86d13359d0de75a8127660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 20 Jan 2025 23:40:43 +0100 Subject: [PATCH 45/57] Add cameras from older TMs --- .../Engines/Game/CGameControlCamera.chunkl | 51 +++++++++++++++++ .../Game/CGameControlCameraOrbital3d.chunkl | 56 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 Src/GBX.NET/Engines/Game/CGameControlCameraOrbital3d.chunkl diff --git a/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl b/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl index f9f6b8fe7..9d1c662d5 100644 --- a/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl @@ -1,6 +1,57 @@ CGameControlCamera 0x0306B000 - inherits: CSceneController +0x001 + vec3 RelativeTargetPos + bool IsFirstPerson + bool CanCameraMove + bool IsFollowing + float MaxSpeed + float PlaneDist + float MinDist + float MaxDist + float Fov + float DefaultFov + bool UseForcedLocation + iso4 ForcedLocation + +0x002 + bool UseOnlyFollowedMobilPosition + +0x003 + id Name + +0x004 + string Name + +0x009 + vec3 RelativeFollowedPos + bool IsFirstPerson + bool CanCameraMove + bool IsFollowing + float MaxSpeed + float PlaneDist + float MinDist + float MaxDist + float Fov + float DefaultFov + bool UseForcedLocation + iso4 ForcedLocation + bool UseOnlyFollowedMobilPosition + id Name + string Name + float MinFov + float MaxFov + bool UseForcedUp + vec3 ForcedUp + float DefaultNearZ + float MinNearZ + float MaxNearZ + float DefaultFarZ + float MinFarZ + float MaxFarZ + bool + 0x00A id Name diff --git a/Src/GBX.NET/Engines/Game/CGameControlCameraOrbital3d.chunkl b/Src/GBX.NET/Engines/Game/CGameControlCameraOrbital3d.chunkl new file mode 100644 index 000000000..7605f695e --- /dev/null +++ b/Src/GBX.NET/Engines/Game/CGameControlCameraOrbital3d.chunkl @@ -0,0 +1,56 @@ +CGameControlCameraOrbital3d 0x0306E000 +- inherits: CGameControlCameraTarget + +0x001 + vec3 RadiusScale + vec2 RotateSpeed + bool OcclusionIsEnable + bool + bool + float MouseBorderMoveSize + float + float + float OcclusionTargetRadius + float OcclusionDistFromHit + float Radius + float Latitude + float Longitude + float RadiusMin + float RadiusMax + float LatitudeMin + float LatitudeMax + +0x002 + float + +0x003 + float WheelSensitivity + +0x004 + float FovKeySensitivity + +0x005 + vec3 RadiusScale + vec2 RotateSpeed + bool OcclusionIsEnable + bool + bool + float MouseBorderMoveSize + float OcclusionTargetRadius + float OcclusionDistFromHit + float Radius + float Latitude + float Longitude + float RadiusMin + float RadiusMax + float LatitudeMin + float LatitudeMax + float + float WheelSensitivity + float FovKeySensitivity + +0x006 + float ZoomKeySensitivity + +0x007 + float DefaultRadius \ No newline at end of file From bfa096febeaf0099ef5db1702589cb5a6458480a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 00:44:30 +0100 Subject: [PATCH 46/57] Fix RefBuffer.Gbx --- .../Engines/Plug/CPlugVehicleMaterial.chunkl | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleMaterial.chunkl b/Src/GBX.NET/Engines/Plug/CPlugVehicleMaterial.chunkl index d9491a464..fd14d59e9 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugVehicleMaterial.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleMaterial.chunkl @@ -1,5 +1,43 @@ CPlugVehicleMaterial 0x090F1000 +0x004 + CPlugBitmap (external) + vec2 + +0x005 + float + float + float + float + +0x009 + byte + float + float + bool + CMwNod (external) + CPlugParticleEmitterModel (external) + CPlugParticleEmitterModel (external) + CPlugParticleEmitterModel (external) + CPlugParticleEmitterModel (external) + +0x00A + CPlugParticleEmitterModel (external) + +0x00B + CPlugParticleEmitterModel (external) + +0x00C + CPlugParticleEmitterModel (external) + +0x00D + CPlugParticleEmitterModel (external) + +0x00E + byte + float + float + 0x00F float float From 0f4c2622a32cf52dbb0afdacfa66f68f773ab34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 01:42:41 +0100 Subject: [PATCH 47/57] TMVehicle and VehicleStruct compatibility for ESWC/TMS --- .../Engines/GameData/CGameItemModel.chunkl | 47 ++++++++++------ .../Plug/CPlugVehicleVisModelShared.chunkl | 33 +++++++++++- .../Plug/CPlugVehicleVisModelShared.cs | 54 +++++++++++++++++++ Src/GBX.NET/Engines/Scene/CScene2d.chunkl | 2 + 4 files changed, 120 insertions(+), 16 deletions(-) create mode 100644 Src/GBX.NET/Engines/Scene/CScene2d.chunkl diff --git a/Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl b/Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl index 88af566b2..8786fd064 100644 --- a/Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl +++ b/Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl @@ -10,35 +10,52 @@ CGameItemModel 0x2E002000 0x000 CSceneMobil Vehicle (external) -0x003 +0x002 // old race interface fid + CScene2d RaceInterfaceFid + +0x003 // LowQualitySolid + CPlugSolid LowQualitySolid (external) + +0x004 CMwNod -0x006 - int +0x006 // DefaultCamIndex + int DefaultCamIndex + +0x007 // old materials + CPlugMaterial MaterialSkin (external) + CPlugMaterial MaterialGlass (external) + CPlugMaterial MaterialDetails (external) 0x008 // Nadeo skin fids CMwNod?[] NadeoSkinFids (external) -0x009 // cameras +0x009 // Cameras CMwNod[]_deprec Cameras (external) -0x00A +0x00A // DecoratorSolid CPlugDecoratorSolid DecoratorSolid (external) -0x00B - CMwNod - CMwNod +0x00B // stem materials + CPlugMaterial StemMaterial (external) + CPlugMaterial StemBumpMaterial (external) 0x00C // race interface fid - CMwNod RaceInterfaceFid + CScene2d RaceInterfaceFid -0x00D - CMwNod[] +0x00D (ForcedSkinsFids) + CMwNod[] ForcedSkinsFids + +0x00E // StadiumCar materials + CPlugMaterial MaterialSkin (external) + CPlugMaterial MaterialGlass (external) + CPlugMaterial MaterialDetails (external) + CPlugMaterial MaterialPilot (external) -0x010 +0x010 (BannerProfileFid) CPlugBitmap BannerProfileFid (external) -0x011 +0x011 // materials CPlugMaterial MaterialSkin (external) CPlugMaterial MaterialGlass (external) CPlugMaterial MaterialDetails (external) @@ -56,13 +73,13 @@ CGameItemModel 0x2E002000 float OrbitalRadiusBase float OrbitalPreviewAngle -0x013 +0x013 (AudioEnvironmentInCar) CPlugAudioEnvironment AudioEnvironmentInCar (external) 0x014 CMwNod -0x015 // item type e +0x015 // ItemTypeE int ItemTypeE 0x019 // model diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl index b78ebf7fb..0f09a1def 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl @@ -9,6 +9,10 @@ CPlugVehicleVisModelShared 0x090E8000 0x00A +0x00C + +0x00D + 0x00F 0x010 @@ -51,4 +55,31 @@ archive VisualWheel archive VisualId id Name - bool \ No newline at end of file + bool + +archive Emitter + int + CPlugParticleEmitterModel + int + int + int + bool + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float + float \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs index a79adeade..0f061151d 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.cs @@ -57,6 +57,56 @@ public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) } } + public partial class Chunk090E800C + { + public int[][]? U01; + + public override void Read(CPlugVehicleVisModelShared n, GbxReader r) + { + var count = r.ReadInt32(); + U01 = new int[count][]; + for (int i = 0; i < count; i++) + { + U01[i] = r.ReadArray(); + } + } + + public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) + { + if (U01 is null) + { + w.Write(0); + return; + } + + w.Write(U01.Length); + for (int i = 0; i < U01.Length; i++) + { + w.WriteArray(U01[i]); + } + } + } + + public partial class Chunk090E800D + { + public override void Read(CPlugVehicleVisModelShared n, GbxReader r) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + n.VisualVehicles[i] ??= new VisualVehicle(); + n.VisualVehicles[i].Emitters = r.ReadArrayReadable(); + } + } + + public override void Write(CPlugVehicleVisModelShared n, GbxWriter w) + { + for (int i = 0; i < n.VisualVehicles.Length; i++) + { + w.WriteArrayWritable(n.VisualVehicles[i].Emitters); + } + } + } + public partial class Chunk090E800F { public override void Read(CPlugVehicleVisModelShared n, GbxReader r) @@ -149,11 +199,15 @@ public override string ToString() } } + [ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)] + public partial class Emitter; + public sealed class VisualVehicle { public VisualArm[] VisualArms { get; set; } = []; public VisualLight[] VisualLights { get; set; } = []; public VisualWheel[] VisualWheels { get; set; } = []; + public Emitter[] Emitters { get; set; } = []; public VisualId? U01 { get; set; } public VisualId? U02 { get; set; } public VisualId? U03 { get; set; } diff --git a/Src/GBX.NET/Engines/Scene/CScene2d.chunkl b/Src/GBX.NET/Engines/Scene/CScene2d.chunkl new file mode 100644 index 000000000..71ee0b4aa --- /dev/null +++ b/Src/GBX.NET/Engines/Scene/CScene2d.chunkl @@ -0,0 +1,2 @@ +CScene2d 0x0A002000 +- inherits: CScene \ No newline at end of file From cdba52c665d851cb09bd892ace7f303bdf2471ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 01:43:04 +0100 Subject: [PATCH 48/57] Add class name --- .../GBX.NET.Generators/Utils/ClassIdParser.cs | 9 ++++++++- Resources/ClassIdManual.txt | Bin 168 -> 302 bytes 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Generators/GBX.NET.Generators/Utils/ClassIdParser.cs b/Generators/GBX.NET.Generators/Utils/ClassIdParser.cs index aa06feeeb..6d2454088 100644 --- a/Generators/GBX.NET.Generators/Utils/ClassIdParser.cs +++ b/Generators/GBX.NET.Generators/Utils/ClassIdParser.cs @@ -67,7 +67,14 @@ public static Dictionary Parse(TextReader reader) // combine engine and class like EECCC000 var classId = (uint)((currentEngineByte << 24) | (classPart << 12)); - result.Add(classId, currentClassName); + if (!result.TryGetValue(classId, out var curName) || string.IsNullOrEmpty(curName)) + { + result[classId] = currentClassName; + } + else + { + throw new Exception($"Duplicate class id {classId:X8} with names '{curName}' and '{currentClassName}'."); + } } else { diff --git a/Resources/ClassIdManual.txt b/Resources/ClassIdManual.txt index 4e0cdf6762024adad9870e87ffaf4ffb01953574..233e1b255d8270afc073d278a5732336b917fbc2 100644 GIT binary patch literal 302 zcmaivK?=e!5Jlfw@D4pfN>?sRQCET}c3VOXR%l}pU3huzPg|&hC}A?mF#pY;*VC|I z&WuRMup(B@*iv)nM2@54OsT(PgXN}tRmG|jbcXazpN#sw6b`TWPe?R1;-KzY+(t3X vm|U5Wy4KW2%uF3#ch$QH&b+)jil3C2Wxv}eWhY&$$(9G Date: Tue, 21 Jan 2025 01:47:20 +0100 Subject: [PATCH 49/57] Update SUPPORTED_GBX_FILE_TYPES.md --- SUPPORTED_GBX_FILE_TYPES.md | 18 ++++++++++++++++-- Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/SUPPORTED_GBX_FILE_TYPES.md b/SUPPORTED_GBX_FILE_TYPES.md index fcc973d4b..694b7a987 100644 --- a/SUPPORTED_GBX_FILE_TYPES.md +++ b/SUPPORTED_GBX_FILE_TYPES.md @@ -15,7 +15,7 @@ Older extensions | Latest extension | Class | Read (whole) | Write | Read (heade | | Shape.Gbx | [CPlugSurface](Src/GBX.NET/Engines/Plug/CPlugSurface.chunkl) | Yes | Yes | | Macroblock.Gbx | [CGameCtnMacroBlockInfo](Src/GBX.NET/Engines/Game/CGameCtnMacroBlockInfo.chunkl) | Yes | Yes | Yes | | SystemConfig.Gbx | [CSystemConfig](Src/GBX.NET/Engines/System/CSystemConfig.chunkl) | Yes | Yes -| | FidCache.Gbx | [CMwRefBuffer](Src/GBX.NET/Engines/MwFoundations/CMwRefBuffer.chunkl) | Yes | Yes +| RefBuffer.Gbx | FidCache.Gbx | [CMwRefBuffer](Src/GBX.NET/Engines/MwFoundations/CMwRefBuffer.chunkl) | Yes | Yes | | Profile.Gbx | [CGamePlayerProfile](Src/GBX.NET/Engines/Game/CGamePlayerProfile.chunkl) | Up to TMF | Up to TMF | Yes | | Spawn.Gbx | [CGameSpawnModel](Src/GBX.NET/Engines/GameData/CGameSpawnModel.chunkl) | Yes | Yes | ConstructionCampaign.Gbx | Campaign.Gbx | [CGameCtnCampaign](Src/GBX.NET/Engines/Game/CGameCtnCampaign.chunkl) | Yes | Yes @@ -39,11 +39,25 @@ Older extensions | Latest extension | Class | Read (whole) | Write | Read (heade | | MotionManagerWeathers.Gbx | [CPlugWeatherModel](Src/GBX.NET/Engines/Plug/CPlugWeatherModel.chunkl) | Up to TMUF | Yes | | RallyLeafManager.Gbx | [CMotionManagerLeaves](Src/GBX.NET/Engines/Motion/CMotionManagerLeaves.chunkl) | Yes | Yes | | GameSkin.Gbx | [CPlugGameSkin](Src/GBX.NET/Engines/Plug/CPlugGameSkin.chunkl) | Yes | Yes -| | VehicleTunings.Gbx | [CPlugVehiclePhyTunings](Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTunings.chunkl) | Up to TM2 | Up to TM2 | Yes +| | VehicleTunings.Gbx | [CPlugVehiclePhyTunings](Src/GBX.NET/Engines/Plug/CPlugVehiclePhyTunings.chunkl) | Up to TM2 | Up to TM2 +| | CtrlCam.Gbx | [CGameControlCamera](Src/GBX.NET/Engines/Game/CGameControlCamera.chunkl) | Yes | Yes +| | CtrlCamTarget.Gbx | [CGameControlCameraTarget](Src/GBX.NET/Engines/Game/CGameControlCameraTarget.chunkl) | Yes | Yes +| | CtrlCamOrbital3d.Gbx | [CGameControlCameraOrbital3d](Src/GBX.NET/Engines/Game/CGameControlCameraOrbital3d.chunkl) | Yes | Yes +| | CtrlCamTmRace.Gbx | [CGameControlCameraTrackManiaRace](Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace.chunkl) | Yes | Yes +| | CtrlCamTmRace2.Gbx | [CGameControlCameraTrackManiaRace2](Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace2.chunkl) | Yes | Yes +| | CtrlCamTmRace3.Gbx | [CGameControlCameraTrackManiaRace3](Src/GBX.NET/Engines/TrackMania/CGameControlCameraTrackManiaRace3.chunkl) | Yes | Yes +| | DecoSolid.Gbx | [CPlugDecoratorSolid](Src/GBX.NET/Engines/CPlug/CPlugDecoratorSolid.chunkl) | Yes | Yes +| | TrackManiaVehicle.Gbx | [CSceneVehicleCar](Src/GBX.NET/Engines/Scene/CSceneVehicleCar.chunkl) | Only TMUF | Only TMUF +| TMVehicle.Gbx | ConstructionVehicle.Gbx | [CGameItemModel](Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl) | Yes | Yes | Yes +| | ParticleModel.Gbx | [CPlugParticleEmitterModel](Src/GBX.NET/Engines/CPlug/CPlugParticleEmitterModel.chunkl) | Up to TMUF | Up to TMUF +| | VehicleStruct.Gbx | [CPlugVehicleVisModelShared](Src/GBX.NET/Engines/GameData/CPlugVehicleVisModelShared.chunkl) | Yes | Yes +| | FuncClouds.Gbx | [CPlugClouds](Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl) | Yes | Yes +| | FuncShader.Gbx | [CFuncShaderLayerUV](Src/GBX.NET/Engines/Func/CFuncShaderLayerUV.chunkl) | Yes | Yes | | ObjectInfo.Gbx | [CGameItemModel](Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl) | Yes | Yes | Yes | | Mobil.Gbx | [CSceneMobil](Src/GBX.NET/Engines/Scene/CSceneMobil.chunkl) | Yes | Yes | | Solid.Gbx | [CPlugSolid](Src/GBX.NET/Engines/Plug/CPlugSolid.cs) | Yes | Yes | | Material.Gbx | [CPlugMaterial](Src/GBX.NET/Engines/Plug/CPlugMaterial.cs) | Up to TM2 | No +| | Shader.Gbx | [CPlugShader](Src/GBX.NET/Engines/Plug/CPlugShader.cs) | Up to TMUF | No | | Texture.Gbx | [CPlugBitmap](Src/GBX.NET/Engines/Plug/CPlugBitmap.cs) | Up to TMUF | No | | Light.Gbx | [CPlugLight](Src/GBX.NET/Engines/Plug/CPlugLight.cs) | Yes | Yes | | Prefab.Gbx | [CPlugPrefab](Src/GBX.NET/Engines/Plug/CPlugPrefab.cs) | Yes | Yes diff --git a/Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl b/Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl index 1ff188cb9..e02138c73 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl @@ -1,7 +1,7 @@ CPlugClouds 0x09180000 0x000 - CMwNod[] + CPlugSolid[] SolidFids (external) float BottomNearZ float BottomFarZ CPlugFileImg ImageColorMin (external) From 583bce7d20ee9c4ccfa026e8cd1d2f05206d300b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 21:07:47 +0100 Subject: [PATCH 50/57] Fix external nodes in IReadable archives --- .../ChunkL/MemberSerializationWriter.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Generators/GBX.NET.Generators/ChunkL/MemberSerializationWriter.cs b/Generators/GBX.NET.Generators/ChunkL/MemberSerializationWriter.cs index ac9d054e3..2f2446ebe 100644 --- a/Generators/GBX.NET.Generators/ChunkL/MemberSerializationWriter.cs +++ b/Generators/GBX.NET.Generators/ChunkL/MemberSerializationWriter.cs @@ -301,32 +301,42 @@ private void AppendRead(int indent, ChunkProperty chunkProperty) var contextual = archives.TryGetValue(chunkProperty.Type.PrimaryType, out var archiveModel) && archiveModel.ChunkLDefinition?.Properties.ContainsKey("contextual") == true; + var comma = false; + if (contextual) { sb.Append('n'); + comma = true; } if (chunkProperty.Properties?.TryGetValue("version", out var version) == true) { - if (contextual) + if (comma) { sb.Append(", "); } sb.Append("version: "); sb.Append(version); + + comma = true; } if (chunkProperty.Properties?.ContainsKey("external") == true && !chunkProperty.Type.IsArray) { - sb.Append(", out "); + if (comma) + { + sb.Append(", "); + } + + sb.Append("out "); if (!self && !isUnknown) { sb.Append("n."); } - sb.Append(name); + sb.Append(char.ToLowerInvariant(name[0]) + name.Substring(1)); sb.Append("File"); } From d291e70db4f6fe83e256a30bd4da6818448b7762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 21:08:11 +0100 Subject: [PATCH 51/57] Add missing EmitterModel --- Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl index 0f09a1def..88bfbeb3d 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugVehicleVisModelShared.chunkl @@ -59,7 +59,7 @@ archive VisualId archive Emitter int - CPlugParticleEmitterModel + CPlugParticleEmitterModel EmitterModel (external) int int int From 2ea50a73e28544961b92ec7693b5f4eeaf804424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 21:25:22 +0100 Subject: [PATCH 52/57] Add missing CGameCtnDecoration header chunks --- .../Engines/Game/CGameCtnDecoration.chunkl | 6 ++- .../Engines/Game/CGameCtnDecoration.cs | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnDecoration.chunkl b/Src/GBX.NET/Engines/Game/CGameCtnDecoration.chunkl index edf6f2a4b..c14505038 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnDecoration.chunkl +++ b/Src/GBX.NET/Engines/Game/CGameCtnDecoration.chunkl @@ -1,9 +1,11 @@ CGameCtnDecoration 0x03038000 - inherits: CGameCtnCollector -0x001 // LightMap +0x000 (header, struct: SMoodRemaping) + +0x001 (header, struct: SLightMap) // LightMap versionb version - int + int // CHmsLightMap Tech 0x011 // DecoSize CGameCtnDecorationSize DecoSize (external) diff --git a/Src/GBX.NET/Engines/Game/CGameCtnDecoration.cs b/Src/GBX.NET/Engines/Game/CGameCtnDecoration.cs index f953c8f1b..e038fc747 100644 --- a/Src/GBX.NET/Engines/Game/CGameCtnDecoration.cs +++ b/Src/GBX.NET/Engines/Game/CGameCtnDecoration.cs @@ -2,6 +2,44 @@ public partial class CGameCtnDecoration { + /// + /// Refers from . + /// + public string RemapFolder { get; set; } = ""; + + /// + /// Refers from . + /// + public CPlugGameSkin? Remapping { get; set; } + + public partial class HeaderChunk03038000 + { + public byte U01; + + public override void ReadWrite(CGameCtnDecoration n, GbxReaderWriter rw) + { + rw.Byte(ref U01); + n.RemapFolder = rw.String(n.RemapFolder); + + if (rw.Reader is not null) + { + n.Remapping = new CPlugGameSkin(); + var headerChunk = new CPlugGameSkin.HeaderChunk090F4000 { Node = n.Remapping }; + n.Remapping.Chunks.Add(headerChunk); + headerChunk.ReadWrite(n.Remapping, rw); + } + + if (rw.Writer is not null) + { + var remapping = n.Remapping ?? new(); + (remapping.Chunks + .OfType() + .FirstOrDefault() ?? new CPlugGameSkin.HeaderChunk090F4000()) + .ReadWrite(remapping, rw); + } + } + } + public override IHeaderChunk? CreateHeaderChunk(uint chunkId) { if (chunkId == 0x090F4000) From 593eea4b97a6e9f716e98578618b1603b8cb4f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 21:31:26 +0100 Subject: [PATCH 53/57] Implement CHmsAmbientOcc --- SUPPORTED_GBX_FILE_TYPES.md | 1 + Src/GBX.NET/Engines/Hms/CHmsAmbientOcc.chunkl | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/SUPPORTED_GBX_FILE_TYPES.md b/SUPPORTED_GBX_FILE_TYPES.md index 694b7a987..b284d0f8a 100644 --- a/SUPPORTED_GBX_FILE_TYPES.md +++ b/SUPPORTED_GBX_FILE_TYPES.md @@ -53,6 +53,7 @@ Older extensions | Latest extension | Class | Read (whole) | Write | Read (heade | | VehicleStruct.Gbx | [CPlugVehicleVisModelShared](Src/GBX.NET/Engines/GameData/CPlugVehicleVisModelShared.chunkl) | Yes | Yes | | FuncClouds.Gbx | [CPlugClouds](Src/GBX.NET/Engines/Plug/CPlugClouds.chunkl) | Yes | Yes | | FuncShader.Gbx | [CFuncShaderLayerUV](Src/GBX.NET/Engines/Func/CFuncShaderLayerUV.chunkl) | Yes | Yes +| | AmbientOcc.Gbx | [CHmsAmbientOcc](Src/GBX.NET/Engines/Hms/CHmsAmbientOcc.chunkl) | Yes | Yes | | ObjectInfo.Gbx | [CGameItemModel](Src/GBX.NET/Engines/GameData/CGameItemModel.chunkl) | Yes | Yes | Yes | | Mobil.Gbx | [CSceneMobil](Src/GBX.NET/Engines/Scene/CSceneMobil.chunkl) | Yes | Yes | | Solid.Gbx | [CPlugSolid](Src/GBX.NET/Engines/Plug/CPlugSolid.cs) | Yes | Yes diff --git a/Src/GBX.NET/Engines/Hms/CHmsAmbientOcc.chunkl b/Src/GBX.NET/Engines/Hms/CHmsAmbientOcc.chunkl index 3959dd683..da22c8c6f 100644 --- a/Src/GBX.NET/Engines/Hms/CHmsAmbientOcc.chunkl +++ b/Src/GBX.NET/Engines/Hms/CHmsAmbientOcc.chunkl @@ -1 +1,9 @@ -CHmsAmbientOcc 0x06026000 \ No newline at end of file +CHmsAmbientOcc 0x06026000 + +0x000 + float + float + int + float + float + float \ No newline at end of file From c5668f6ab4ece09ece31a6c013ed60bd5874417f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 21:54:08 +0100 Subject: [PATCH 54/57] Tweaks --- SUPPORTED_GBX_FILE_TYPES.md | 2 ++ Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SUPPORTED_GBX_FILE_TYPES.md b/SUPPORTED_GBX_FILE_TYPES.md index b284d0f8a..7812ebce3 100644 --- a/SUPPORTED_GBX_FILE_TYPES.md +++ b/SUPPORTED_GBX_FILE_TYPES.md @@ -24,6 +24,7 @@ Older extensions | Latest extension | Class | Read (whole) | Write | Read (heade | TMDecorationSize.Gbx | DecorationSize.Gbx | [CGameCtnDecorationSize](Src/GBX.NET/Engines/Game/CGameCtnDecorationSize.chunkl) | Yes | Yes | Yes | TMDecorationMood.Gbx | DecorationMood.Gbx | [CGameCtnDecorationMood](Src/GBX.NET/Engines/Game/CGameCtnDecorationMood.chunkl) | Yes | Yes | Yes | TMDecorationAudio.Gbx | DecorationAudio.Gbx | [CGameCtnDecorationAudio](Src/GBX.NET/Engines/Game/CGameCtnDecorationAudio.chunkl) | Yes | Yes | Yes +| | Scene3d.Gbx | [CSceneLayout](Src/GBX.NET/Engines/Scene/CSceneLayout.chunkl) | Yes | Yes | TMEDClassic.Gbx | EDClassic.Gbx | [CGameCtnBlockInfoClassic](Src/GBX.NET/Engines/Game/CGameCtnBlockInfoClassic.chunkl) | Yes | Yes | Yes | TMEDClip.Gbx | EDClip.Gbx | [CGameCtnBlockInfoClip](Src/GBX.NET/Engines/Game/CGameCtnBlockInfoClip.chunkl) | Yes | Yes | Yes | TMEDFlat.Gbx | EDFlat.Gbx | [CGameCtnBlockInfoFlat](Src/GBX.NET/Engines/Game/CGameCtnBlockInfoFlat.chunkl) | Yes | Yes | Yes @@ -62,5 +63,6 @@ Older extensions | Latest extension | Class | Read (whole) | Write | Read (heade | | Texture.Gbx | [CPlugBitmap](Src/GBX.NET/Engines/Plug/CPlugBitmap.cs) | Up to TMUF | No | | Light.Gbx | [CPlugLight](Src/GBX.NET/Engines/Plug/CPlugLight.cs) | Yes | Yes | | Prefab.Gbx | [CPlugPrefab](Src/GBX.NET/Engines/Plug/CPlugPrefab.cs) | Yes | Yes +| | Wagon.Gbx | [CPlugTrainWagonModel](Src/GBX.NET/Engines/Plug/CPlugTrainWagonModel.cs) | Yes | Yes - 1Safety reasons. Consider extracting `CGameCtnGhost` from `CGameCtnReplayRecord`, transfer it over to `CGameCtnMediaBlockGhost`, add it to `CGameCtnMediaClip`, and save it as `.Clip.Gbx`, which you can then import in MediaTracker. \ No newline at end of file diff --git a/Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl b/Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl index a5e2fc662..8478d4118 100644 --- a/Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl +++ b/Src/GBX.NET/Engines/Function/CFuncShaderLayerUV.chunkl @@ -33,8 +33,7 @@ CFuncShaderLayerUV 0x05015000 0x013 (base: 0x00A) 0x014 - float - float + vec2 float float From e879e946020bc614609ba2564b00210cfc6f3066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Tue, 21 Jan 2025 22:26:13 +0100 Subject: [PATCH 55/57] Add BorderRGB and AtlasCountUVs --- Src/GBX.NET/Engines/Plug/CPlugBitmap.chunkl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Src/GBX.NET/Engines/Plug/CPlugBitmap.chunkl b/Src/GBX.NET/Engines/Plug/CPlugBitmap.chunkl index bc39b9df1..027c6fa4d 100644 --- a/Src/GBX.NET/Engines/Plug/CPlugBitmap.chunkl +++ b/Src/GBX.NET/Engines/Plug/CPlugBitmap.chunkl @@ -6,7 +6,7 @@ CPlugBitmap 0x09011000 float MipMapLowerAlpha float BumpScaleFactor float MipMapLodBiasDefault - int + int BorderRGB int 0x017 @@ -19,7 +19,7 @@ CPlugBitmap 0x09011000 float MipMapLowerAlpha float BumpScaleFactor float MipMapLodBiasDefault - int + int BorderRGB if Image != null CMwNod @@ -36,7 +36,7 @@ CPlugBitmap 0x09011000 int16 0x01E - Vec2[] + vec2[] AtlasCountUVs 0x01F uint From 071c6901520890e55eaaedf8ebfb42cb3f4bb480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Wed, 22 Jan 2025 13:42:17 +0100 Subject: [PATCH 56/57] Update GBX.NET.PAK to 2.1.0 --- Src/GBX.NET.PAK/GBX.NET.PAK.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/GBX.NET.PAK/GBX.NET.PAK.csproj b/Src/GBX.NET.PAK/GBX.NET.PAK.csproj index 2919d42aa..a5cd2dc7a 100644 --- a/Src/GBX.NET.PAK/GBX.NET.PAK.csproj +++ b/Src/GBX.NET.PAK/GBX.NET.PAK.csproj @@ -2,7 +2,7 @@ GBX.NET.PAK - 2.0.0 + 2.1.0 BigBang1112 Support for Pak (NadeoPak) package files, integrated with GBX.NET. Copyright (c) 2024 Petr Pivoňka From d6989619495be40c3103a3ca1f27c6d0606d753c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Wed, 22 Jan 2025 13:43:43 +0100 Subject: [PATCH 57/57] Update GBX.NET.Tool.CLI to 0.5.1 --- Src/GBX.NET.Tool.CLI/GBX.NET.Tool.CLI.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/GBX.NET.Tool.CLI/GBX.NET.Tool.CLI.csproj b/Src/GBX.NET.Tool.CLI/GBX.NET.Tool.CLI.csproj index 367c3f7b1..8b4a9e3c7 100644 --- a/Src/GBX.NET.Tool.CLI/GBX.NET.Tool.CLI.csproj +++ b/Src/GBX.NET.Tool.CLI/GBX.NET.Tool.CLI.csproj @@ -2,7 +2,7 @@ GBX.NET.Tool.CLI - 0.5.0 + 0.5.1 BigBang1112 CLI implementation for the GBX.NET tool framework using Spectre.Console. Copyright (c) 2024 Petr Pivoňka