├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── docs ├── README.md ├── _config.yml └── img │ ├── GameBoxView Formatted Text.png │ └── GameBoxView.PNG └── src ├── .editorconfig ├── ManiaPlanetSharp.CustomParserGenerationTest ├── App.config ├── ManiaPlanetSharp.CustomParserGenerationTest.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── ManiaPlanetSharp.GameBox.AutoGenerated ├── ChunkParsers.tt ├── Classes.tt ├── GlobalSuppressions.cs ├── ManiaPlanetSharp.GameBox.AutoGenerated.csproj └── StructParsers.tt ├── ManiaPlanetSharp.GameBox.Parsing.Benchmark ├── ManiaPlanetSharp.GameBox.Parsing.Benchmark.csproj ├── ParserBenchmark.cs ├── PreGeneratedParserBenchmark.cs ├── Program.cs ├── RuntimeGeneratedParserBenchmark.cs └── TestMap.Gbx ├── ManiaPlanetSharp.GameBox.Parsing.ParserGenerationIntegrityTest ├── ManiaPlanetSharp.GameBox.Parsing.ParserGenerationIntegrityTest.csproj ├── Program.cs └── TestMap.Gbx ├── ManiaPlanetSharp.GameBoxView ├── App.xaml ├── App.xaml.cs ├── AssemblyInfo.cs ├── GameBoxMetadataViewModel.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── ManiaPlanetSharp.GameBoxView.csproj ├── RelayCommand.cs ├── TreeNodes │ ├── Advanced │ │ ├── ChunkTreeNode.cs │ │ ├── DecorationTreeNode.cs │ │ ├── DependencyTreeNode.cs │ │ ├── EmbeddedItemTreeNode.cs │ │ ├── FileReferenceTreeNode.cs │ │ ├── PlayerTreeNode.cs │ │ ├── ReferenceTableFolderTreeNode.cs │ │ ├── ReferenceTableTreeNode.cs │ │ ├── TimeTreeNode.cs │ │ ├── TimesTreeNode.cs │ │ └── VehicleTreeNode.cs │ ├── ButtonTreeNode.cs │ ├── FormattedTextTreeNode.cs │ ├── HyperlinkTreeNode.cs │ ├── ImageTreeNode.cs │ ├── Metadata │ │ ├── EmbeddedMapTreeNode.cs │ │ ├── FileMetadataTreeNode.cs │ │ ├── ItemMetadataTreeNode.cs │ │ ├── MacroblockMetadataTreeNode.cs │ │ ├── MapMetadataTreeNode.cs │ │ └── MetadataTreeNode.cs │ └── TextTreeNode.cs ├── TreeViewItemHelper.cs └── Utils.cs ├── ManiaPlanetSharp.ParserTest ├── ManiaPlanetSharp.ParserTest.csproj └── Program.cs ├── ManiaPlanetSharp.sln └── ManiaPlanetSharp ├── GameBox ├── Chunk.cs ├── ClassId.cs ├── GameBoxFile.cs ├── MetadataProviders │ ├── CollectorMetadataProvider.cs │ ├── ItemMetadataProvider.cs │ ├── MacroBlockMetadataProvider.cs │ ├── MapMetadataProvider.cs │ ├── MetadataProvider.cs │ └── ReplayMetadataProvider.cs ├── Node.cs ├── ParseException.cs ├── Parsing │ ├── Chunks │ │ ├── Collector │ │ │ ├── CollectorBasicMetadataChunk.cs │ │ │ ├── CollectorBrowserMetadataChunk.cs │ │ │ ├── CollectorCatalogChunk.cs │ │ │ ├── CollectorDefaultSkinChunk.cs │ │ │ ├── CollectorDescriptionChunk.cs │ │ │ ├── CollectorIconChunk.cs │ │ │ ├── CollectorIconMetadataChunk.cs │ │ │ ├── CollectorLightmapCacheIdChunk.cs │ │ │ ├── CollectorListChunk.cs │ │ │ ├── CollectorMetadataChunk.cs │ │ │ └── CollectorNameChunk.cs │ │ ├── Ghost │ │ │ ├── GhostCheckpointEntriesChunk.cs │ │ │ ├── GhostChunk.cs │ │ │ ├── GhostDataChunk.cs │ │ │ ├── GhostDisplayChunk.cs │ │ │ ├── GhostLightTrailColorChunk.cs │ │ │ ├── GhostLoginChunk.cs │ │ │ ├── GhostPlayerMobilIdChunk.cs │ │ │ ├── GhostRaceTimeChunk.cs │ │ │ ├── GhostRespawnCountChunk.cs │ │ │ ├── GhostStuntScoreChunk.cs │ │ │ ├── GhostUidChunk.cs │ │ │ ├── GhostUnknown2Chunk.cs │ │ │ ├── GhostUnknown3Chunk.cs │ │ │ ├── GhostUnknown4Chunk.cs │ │ │ ├── GhostUnknown5Chunk.cs │ │ │ ├── GhostUnknown6Chunk.cs │ │ │ └── GhostUnknown7Chunk.cs │ │ ├── Map │ │ │ ├── MapAuthorChunk.cs │ │ │ ├── MapChallengeParameterChunk.cs │ │ │ ├── MapCheckpointsChunk.cs │ │ │ ├── MapChunk.cs │ │ │ ├── MapCommonChunk.cs │ │ │ ├── MapCommunityChunk.cs │ │ │ ├── MapCoordinateChunk.cs │ │ │ ├── MapCustomMusicChunk.cs │ │ │ ├── MapDescriptionChunk.cs │ │ │ ├── MapEmbeddedItemsChunk.cs │ │ │ ├── MapGlobalClipChunk.cs │ │ │ ├── MapGmCamArchiveChunk.cs │ │ │ ├── MapLapCountChunk.cs │ │ │ ├── MapLightmapChunk.cs │ │ │ ├── MapMediaTrackerChunk.cs │ │ │ ├── MapModpackChunk.cs │ │ │ ├── MapPasswordChunk.cs │ │ │ ├── MapPasswordChunkOld.cs │ │ │ ├── MapPlaymodeChunk.cs │ │ │ ├── MapThumbnailChunk.cs │ │ │ ├── MapTimeChunk.cs │ │ │ ├── MapTimelimitChunk.cs │ │ │ ├── MapTimelimitTimeChunk.cs │ │ │ ├── MapTipChunk.cs │ │ │ ├── MapVehicleChunk.cs │ │ │ └── MapVersionChunk.cs │ │ ├── MediaTracker │ │ │ └── MediaTrackerTrianglesChunk.cs │ │ ├── Object │ │ │ ├── ObjectAnchorChunk.cs │ │ │ ├── ObjectAudioEnvironmentChunk.cs │ │ │ ├── ObjectBannerProfileChunk.cs │ │ │ ├── ObjectBaseAttributesChunk.cs │ │ │ ├── ObjectCameraIndexChunk.cs │ │ │ ├── ObjectCamerasChunk.cs │ │ │ ├── ObjectDecoratorSolidChunk.cs │ │ │ ├── ObjectDefaultSkinChunk.cs │ │ │ ├── ObjectGroundPointChunk.cs │ │ │ ├── ObjectItemTypeChunk.cs │ │ │ ├── ObjectMaterialChunk.cs │ │ │ ├── ObjectModelChunk.cs │ │ │ ├── ObjectNadeoSkinFileChunk.cs │ │ │ ├── ObjectRaceInterfaceChunk.cs │ │ │ ├── ObjectTypeChunk.cs │ │ │ ├── ObjectUnknownChunk.cs │ │ │ └── ObjectUsabilityChunk.cs │ │ ├── Other │ │ │ ├── GameSkinChunk.cs │ │ │ ├── PackDescriptionChunk.cs │ │ │ ├── PhysicalModelChunk.cs │ │ │ ├── VisualModelChunk.cs │ │ │ └── WaypointSpecialPropertyChunk.cs │ │ ├── Replay │ │ │ ├── ReplayCommunityChunk.cs │ │ │ ├── ReplayGhostsChunk.cs │ │ │ ├── ReplayMainChunk.cs │ │ │ ├── ReplayUnknown2Chunk.cs │ │ │ ├── ReplayUnknownChunk.cs │ │ │ └── ReplayVersionChunk.cs │ │ └── TMUnlimiter │ │ │ ├── ChallengeBackendChunk.cs │ │ │ ├── LegacyParameterSetChunk.cs │ │ │ └── LegacyScriptChunk.cs │ ├── GameBoxReader.cs │ ├── GlobalParserSettings.cs │ ├── Parser.cs │ ├── ParserFactory.cs │ ├── ParserGeneration │ │ ├── Attributes │ │ │ ├── ArrayAttribute.cs │ │ │ ├── ChunkAttribute.cs │ │ │ ├── ConditionAttribute.cs │ │ │ ├── CustomParserMethodAttribute.cs │ │ │ ├── CustomStructAttribute.cs │ │ │ └── PropertyAttribute.cs │ │ ├── Field.cs │ │ ├── ParserCodeGenerator.cs │ │ ├── ParserGenerator.cs │ │ └── ParserGeneratorException.cs │ ├── ParsingErrorLogger.cs │ └── Utils │ │ └── ParsedValueMappings.cs └── Types │ ├── FileFormat.cs │ ├── FileReference.cs │ ├── GameCtnBlockSkin.cs │ ├── Size2D.cs │ ├── Size3D.cs │ ├── Vector2D.cs │ └── Vector3D.cs ├── GlobalSuppressions.cs ├── ManiaPlanetSharp.csproj ├── Properties ├── Resources.Designer.cs ├── Resources.resx └── launchSettings.json ├── TMUnlimiter ├── BlockData.cs ├── ChallengeBackend.cs ├── DecorationVisibility.cs ├── LegacyMediaClipResource.cs ├── LegacyScript.cs ├── LegacyScriptExecutionType.cs ├── Parameter.cs ├── ParameterFunction.cs ├── ParameterSet.cs ├── ParameterValueType.cs ├── SpawnPointAlterMethod.cs ├── TrackVersion.cs ├── Vanilla │ └── VersionBackend.cs ├── Version04 │ └── VersionBackend.cs ├── Version06 │ ├── BlockData.cs │ └── VersionBackend.cs ├── Version07 │ ├── BlockData.cs │ └── VersionBackend.cs ├── Version11 │ ├── BlockData.cs │ └── VersionBackend.cs ├── Version12 │ ├── BlockData.cs │ └── VersionBackend.cs ├── Version13 │ ├── BlockData.cs │ ├── BlockFlags.cs │ ├── ChallengeFlags.cs │ └── VersionBackend.cs ├── Version20 │ └── VersionBackend.cs └── VersionBackend.cs └── Utilities ├── IndentingStringBuilder.cs ├── MiniLZO.cs └── Utils.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | *.publishproj 131 | 132 | # NuGet Packages Directory 133 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 134 | #packages/ 135 | 136 | # Windows Azure Build Output 137 | csx 138 | *.build.csdef 139 | 140 | # Windows Store app package directory 141 | AppPackages/ 142 | 143 | # Others 144 | sql/ 145 | *.Cache 146 | ClientBin/ 147 | [Ss]tyle[Cc]op.* 148 | ~$* 149 | *~ 150 | *.dbmdl 151 | *.[Pp]ublish.xml 152 | *.pfx 153 | *.publishsettings 154 | 155 | # RIA/Silverlight projects 156 | Generated_Code/ 157 | 158 | # Backup & report files from converting an old project file to a newer 159 | # Visual Studio version. Backup files are not needed, because we have git ;-) 160 | _UpgradeReport_Files/ 161 | Backup*/ 162 | UpgradeLog*.XML 163 | UpgradeLog*.htm 164 | 165 | # SQL Server files 166 | App_Data/*.mdf 167 | App_Data/*.ldf 168 | 169 | ############# 170 | ## Windows detritus 171 | ############# 172 | 173 | # Windows image file caches 174 | Thumbs.db 175 | ehthumbs.db 176 | 177 | # Folder config file 178 | Desktop.ini 179 | 180 | # Recycle Bin used on file shares 181 | $RECYCLE.BIN/ 182 | 183 | # Mac crap 184 | .DS_Store 185 | 186 | 187 | ############# 188 | ## Python 189 | ############# 190 | 191 | *.py[cod] 192 | 193 | # Packages 194 | *.egg 195 | *.egg-info 196 | dist/ 197 | build/ 198 | eggs/ 199 | parts/ 200 | var/ 201 | sdist/ 202 | develop-eggs/ 203 | .installed.cfg 204 | 205 | # Installer logs 206 | pip-log.txt 207 | 208 | # Unit test / coverage reports 209 | .coverage 210 | .tox 211 | 212 | #Translations 213 | *.mo 214 | 215 | #Mr Developer 216 | .mr.developer.cfg 217 | *.jrs 218 | *.ide 219 | 220 | 221 | AeroSuite.sln.GhostDoc.xml 222 | old/ManiaPlanetSharp/.vs 223 | /ManiaPlanetSharp.zip 224 | src/.vs/** 225 | src/ManiaPlanetSharp.GameBox.AutoGenerated/ManiaPlanetSharp.dll 226 | src/ManiaPlanetSharp.dll 227 | src/ManiaPlanetSharp.GameBox.AutoGenerated/ChunkParsers.cs 228 | src/ManiaPlanetSharp.GameBox.AutoGenerated/Classes.cs 229 | src/ManiaPlanetSharp.GameBox.AutoGenerated/StructParsers.cs 230 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2020 Stefan Baumann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /docs/img/GameBoxView Formatted Text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefan-baumann/ManiaPlanetSharp/e5b95bcd806bf2ebb0ea8776576861ccb6e4cd83/docs/img/GameBoxView Formatted Text.png -------------------------------------------------------------------------------- /docs/img/GameBoxView.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefan-baumann/ManiaPlanetSharp/e5b95bcd806bf2ebb0ea8776576861ccb6e4cd83/docs/img/GameBoxView.PNG -------------------------------------------------------------------------------- /src/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # CS0618: Type or member is obsolete 4 | dotnet_diagnostic.CS0618.severity = none 5 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.CustomParserGenerationTest/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.CustomParserGenerationTest/ManiaPlanetSharp.CustomParserGenerationTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F3949E03-50D8-4C0F-A723-2C23F69D51EA} 8 | Exe 9 | ManiaPlanetSharp.CustomParserGenerationTest 10 | ManiaPlanetSharp.CustomParserGenerationTest 11 | v4.6.1 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | .editorconfig 51 | 52 | 53 | 54 | 55 | 56 | {2461a29a-da40-4a58-b4f4-9c1f3762c5b2} 57 | ManiaPlanetSharp.GameBox.AutoGenerated 58 | 59 | 60 | {ae645ff0-e68e-4c6f-b17d-6758f4596164} 61 | ManiaPlanetSharp 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.CustomParserGenerationTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ManiaPlanetSharp.CustomParserGenerationTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ManiaPlanetSharp.CustomParserGenerationTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f3949e03-50d8-4c0f-a723-2c23f69d51ea")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.AutoGenerated/ChunkParsers.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="true" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System" #> 3 | <#@ assembly name="System.Console, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #> 4 | <#@ assembly name="System.Core" #> 5 | <#@ assembly name="System.Reflection" #> 6 | <#@ assembly name="System.Linq" #> 7 | <#@ assembly name="System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #> 8 | <#@ assembly name="netstandard" #> 9 | <#@ assembly name="mscorlib" #> 10 | <#@ assembly name="ManiaPlanetSharp.dll" #> 11 | <#@ import namespace="System" #> 12 | <#@ import namespace="System.Collections" #> 13 | <#@ import namespace="System.Collections.Generic" #> 14 | <#@ import namespace="System.Diagnostics" #> 15 | <#@ import namespace="System.Reflection" #> 16 | <#@ import namespace="System.Runtime" #> 17 | <#@ import namespace="System.Runtime.CompilerServices" #> 18 | <#@ import namespace="System.Runtime.InteropServices" #> 19 | <#@ import namespace="System.Linq" #> 20 | <#@ import namespace="System.Text" #> 21 | <#@ import namespace="System.Text.RegularExpressions" #> 22 | <#@ import namespace="ManiaPlanetSharp.GameBox" #> 23 | <#@ import namespace="ManiaPlanetSharp.GameBox.Parsing" #> 24 | <#@ import namespace="ManiaPlanetSharp.GameBox.Parsing.ParserGeneration" #> 25 | <#@ output extension=".cs" #> 26 | using System; 27 | using System.Collections; 28 | using System.Collections.Generic; 29 | using ManiaPlanetSharp.GameBox.Parsing.Chunks; 30 | 31 | namespace ManiaPlanetSharp.GameBox.Parsing.ParserGeneration.AutoGenerated 32 | { 33 | public static partial class AutoGeneratedParsers 34 | { 35 | public static Dictionary> ChunkParsers { get; } = new Dictionary> { 36 | <# 37 | var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(p => !p.IsDynamic); 38 | var chunkTypes = assemblies.SelectMany(a => a.GetExportedTypes().Where(t => t != typeof(Chunk) && typeof(Chunk).IsAssignableFrom(t) && t.CustomAttributes.Where(x => x.AttributeType == typeof(ChunkAttribute)).Any())); 39 | foreach (var chunkType in chunkTypes) 40 | { 41 | #> { typeof(<#= chunkType #>), new <#= chunkType.Name #>Parser() }, 42 | <# 43 | } 44 | #> 45 | }; 46 | } 47 | <# 48 | foreach (var chunkType in chunkTypes) 49 | { 50 | Console.WriteLine($"Generating parser for type {chunkType.Name}"); 51 | string code = (string)typeof(ParserCodeGenerator).GetMethod(nameof(ParserCodeGenerator.GenerateChunkParserString), BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(chunkType).Invoke(null, null); 52 | List> ids = (List>)typeof(ParserCodeGenerator).GetMethod(nameof(ParserCodeGenerator.GetParserChunkIds), BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(chunkType).Invoke(null, null); 53 | #> 54 | 55 | public class <#= chunkType.Name #>Parser 56 | : PregeneratedChunkParser<<#= chunkType #>> 57 | { 58 | public override List> ParseableIds => new List>() { <#= string.Join(", ", ids.Select(i => $"Tuple.Create(0x{i.Item1:X8}U, {(i.Item2 ? "true" : "false")})")) #> }; 59 | 60 | public override <#= chunkType #> Parse(GameBoxReader reader, uint chunkId) 61 | { 62 | <#= string.Join(Environment.NewLine, code/*.Replace(chunkType.Name, chunkType.FullName)*/.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).Select(line => $"\t\t\t{line}")) #> 63 | } 64 | } 65 | <# 66 | } 67 | #> 68 | } 69 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.AutoGenerated/Classes.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ assembly name="netstandard" #> 4 | <#@ assembly name="ManiaPlanetSharp.dll" #> 5 | <#@ import namespace="System.Linq" #> 6 | <#@ import namespace="System.Text" #> 7 | <#@ import namespace="System.Collections.Generic" #> 8 | <#@ import namespace="System.Reflection" #> 9 | <#@ import namespace="ManiaPlanetSharp.GameBox" #> 10 | <#@ import namespace="ManiaPlanetSharp.GameBox.Parsing" #> 11 | <#@ import namespace="ManiaPlanetSharp.GameBox.Parsing.ParserGeneration" #> 12 | <#@ output extension=".cs" #> 13 | <# 14 | Assembly mpSharp = Assembly.GetAssembly(typeof(Chunk)); 15 | var chunks = mpSharp.GetExportedTypes().Where(t => typeof(Chunk).IsAssignableFrom(t) && t != typeof(Chunk) && t.GetCustomAttributes().Any()); 16 | var classes = chunks.SelectMany(c => c.GetCustomAttributes().Select(ca => Tuple.Create(ca.Id, c))).GroupBy(c => c.Item1 & ~0xFFFU); 17 | foreach (var @class in classes) 18 | { 19 | var classId = @class.Key; 20 | #>//<#= KnownClassIds.GetClassName(classId) #> 21 | <# 22 | foreach (var chunk in @class) 23 | { 24 | #> 25 | // - Chunk <#= chunk.Item2.Name #> (<#= $"0x{chunk.Item1:X8}" #>) 26 | <# 27 | } 28 | #> 29 | 30 | <# 31 | } 32 | #> -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.AutoGenerated/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 |  2 | // This file is used by Code Analysis to maintain SuppressMessage 3 | // attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given 5 | // a specific target and scoped to a namespace, type, member, etc. 6 | 7 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0017:Simplify object initialization", Justification = "")] -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.AutoGenerated/StructParsers.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="true" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System" #> 3 | <#@ assembly name="System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #> 4 | <#@ assembly name="System.Console, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #> 5 | <#@ assembly name="System.Core" #> 6 | <#@ assembly name="System.Linq" #> 7 | <#@ assembly name="System.Reflection" #> 8 | <#@ assembly name="netstandard" #> 9 | <#@ assembly name="mscorlib" #> 10 | <#@ assembly name="ManiaPlanetSharp.dll" #> 11 | <#@ import namespace="System" #> 12 | <#@ import namespace="System.Collections" #> 13 | <#@ import namespace="System.Collections.Generic" #> 14 | <#@ import namespace="System.Diagnostics" #> 15 | <#@ import namespace="System.Reflection" #> 16 | <#@ import namespace="System.Runtime" #> 17 | <#@ import namespace="System.Runtime.InteropServices" #> 18 | <#@ import namespace="System.Linq" #> 19 | <#@ import namespace="System.Text" #> 20 | <#@ import namespace="System.Text.RegularExpressions" #> 21 | <#@ import namespace="ManiaPlanetSharp.GameBox" #> 22 | <#@ import namespace="ManiaPlanetSharp.GameBox.Parsing" #> 23 | <#@ import namespace="ManiaPlanetSharp.GameBox.Parsing.ParserGeneration" #> 24 | <#@ output extension=".cs" #> 25 | using System; 26 | using System.Diagnostics; 27 | using System.Collections; 28 | using System.Collections.Generic; 29 | using System.Linq; 30 | using ManiaPlanetSharp.GameBox.Parsing.Chunks; 31 | 32 | namespace ManiaPlanetSharp.GameBox.Parsing.ParserGeneration.AutoGenerated 33 | { 34 | public static partial class AutoGeneratedParsers 35 | { 36 | public static Dictionary> StructParsers { get; } = new Dictionary> { 37 | <# 38 | var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(p => !p.IsDynamic); 39 | var structTypes = assemblies.SelectMany(a => a.GetExportedTypes().Where(t => t.CustomAttributes.Where(x => x.AttributeType == typeof(CustomStructAttribute)).Any())); 40 | foreach (var structType in structTypes) 41 | { 42 | #> { typeof(<#= structType #>), new <#= structType.Name #>Parser() }, 43 | <# 44 | } 45 | #> 46 | }; 47 | } 48 | 49 | 50 | <# 51 | foreach (var structType in structTypes) 52 | { 53 | System.Console.WriteLine($"Generating parser for type {structType.Name}"); 54 | string code = (string)typeof(ParserCodeGenerator).GetMethod(nameof(ParserCodeGenerator.GenerateStructParserString), BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(structType).Invoke(null, null); 55 | #> 56 | 57 | public class <#= structType.Name #>Parser 58 | : PregeneratedCustomStructParser<<#= structType #>> 59 | { 60 | public override <#= structType #> Parse(GameBoxReader reader) 61 | { 62 | <#= string.Join(Environment.NewLine, code/*.Replace(structType.Name, structType.FullName)*/.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).Select(line => $"\t\t\t{line}")) #> 63 | } 64 | } 65 | <# 66 | } 67 | #> 68 | } 69 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.Benchmark/ManiaPlanetSharp.GameBox.Parsing.Benchmark.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.Benchmark/ParserBenchmark.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace ManiaPlanetSharp.GameBox.Parsing.Benchmark 9 | { 10 | public abstract class ParserBenchmark 11 | { 12 | protected string gbxPath; 13 | protected byte[] file; 14 | protected GameBoxFile parsedFile; 15 | 16 | [GlobalSetup] 17 | public virtual void Setup() 18 | { 19 | this.gbxPath = Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.Gbx").FirstOrDefault(); 20 | if (!File.Exists(this.gbxPath)) 21 | { 22 | throw new FileNotFoundException("Could not find test gbx file."); 23 | } 24 | Console.WriteLine($"Test file: {gbxPath}"); 25 | this.file = File.ReadAllBytes(this.gbxPath); 26 | Console.WriteLine($"File length: {this.file.Length} bytes"); 27 | this.parsedFile = GameBoxFile.Parse(new MemoryStream(this.file)); 28 | Console.WriteLine($"Uncompressed body length: {this.parsedFile.GetUncompressedBodyData().Length} bytes"); 29 | } 30 | 31 | [Benchmark] 32 | public void ParseHeader() 33 | { 34 | GameBoxFile.Parse(new MemoryStream(file)); 35 | } 36 | 37 | [Benchmark] 38 | public void ParseBody() 39 | { 40 | this.parsedFile.ParseBody(); 41 | } 42 | 43 | [Benchmark] 44 | public void ParseFullFile() 45 | { 46 | GameBoxFile.Parse(new MemoryStream(file)).ParseBody(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.Benchmark/PreGeneratedParserBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace ManiaPlanetSharp.GameBox.Parsing.Benchmark 7 | { 8 | public class PreGeneratedParserBenchmark 9 | : ParserBenchmark 10 | { 11 | public override void Setup() 12 | { 13 | base.Setup(); 14 | 15 | GlobalParserSettings.UseDynamicallyCompiledChunkParsers = false; 16 | GlobalParserSettings.UsePrecompiledParsersIfPresent = true; 17 | ParserFactory.ClearParsers(); 18 | ParserFactory.InitializePrecompiledParsers(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.Benchmark/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | using System; 3 | 4 | namespace ManiaPlanetSharp.GameBox.Parsing.Benchmark 5 | { 6 | public static class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); 11 | Console.ReadKey(true); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.Benchmark/RuntimeGeneratedParserBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Benchmark 6 | { 7 | public class RuntimeGeneratedParserBenchmark 8 | : ParserBenchmark 9 | { 10 | public override void Setup() 11 | { 12 | base.Setup(); 13 | 14 | ParserFactory.ClearParsers(); 15 | GlobalParserSettings.UseDynamicallyCompiledChunkParsers = true; 16 | GlobalParserSettings.UsePrecompiledParsersIfPresent = false; 17 | ParserFactory.ClearParsers(); 18 | ParserFactory.ScanForParseableChunks(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.Benchmark/TestMap.Gbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefan-baumann/ManiaPlanetSharp/e5b95bcd806bf2ebb0ea8776576861ccb6e4cd83/src/ManiaPlanetSharp.GameBox.Parsing.Benchmark/TestMap.Gbx -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.ParserGenerationIntegrityTest/ManiaPlanetSharp.GameBox.Parsing.ParserGenerationIntegrityTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.ParserGenerationIntegrityTest/Program.cs: -------------------------------------------------------------------------------- 1 | using KellermanSoftware.CompareNetObjects; 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | 6 | namespace ManiaPlanetSharp.GameBox.Parsing.ParserGenerationIntegrityTest 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | var gbxPath = Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.Gbx").FirstOrDefault(); 13 | if (!File.Exists(gbxPath)) 14 | { 15 | throw new FileNotFoundException("Could not find test gbx file."); 16 | } 17 | Console.WriteLine($"Test file: {gbxPath}"); 18 | 19 | var compareLogic = new CompareLogic(new ComparisonConfig() { MaxDifferences = 10 }); 20 | 21 | //Runtime 22 | ParserFactory.ClearParsers(); 23 | GlobalParserSettings.UseDynamicallyCompiledChunkParsers = true; 24 | GlobalParserSettings.UsePrecompiledParsersIfPresent = false; 25 | ParserFactory.ClearParsers(); 26 | ParserFactory.ScanForParseableChunks(); 27 | 28 | var runtimeFile = GameBoxFile.Parse(gbxPath); 29 | var runtimeBody = runtimeFile.ParseBody().ToList(); 30 | 31 | //Pregenerated 32 | GlobalParserSettings.UseDynamicallyCompiledChunkParsers = false; 33 | GlobalParserSettings.UsePrecompiledParsersIfPresent = true; 34 | ParserFactory.ClearParsers(); 35 | ParserFactory.InitializePrecompiledParsers(); 36 | 37 | var pregeneratedFile = GameBoxFile.Parse(gbxPath); 38 | var pregeneratedBody = runtimeFile.ParseBody().ToList(); 39 | 40 | Console.WriteLine("\n\n# Header and general file metadata"); 41 | var fileResult = compareLogic.Compare(pregeneratedFile, runtimeFile); 42 | if (fileResult.AreEqual) 43 | { 44 | Console.WriteLine("Same data. OK."); 45 | } 46 | else 47 | { 48 | Console.WriteLine(fileResult.DifferencesString); 49 | } 50 | 51 | Console.WriteLine("\n\n# Body"); 52 | var bodyResult = compareLogic.Compare(pregeneratedBody, runtimeBody); 53 | if (bodyResult.AreEqual) 54 | { 55 | Console.WriteLine("Same data. OK."); 56 | } 57 | else 58 | { 59 | Console.WriteLine(bodyResult.DifferencesString); 60 | } 61 | 62 | 63 | Console.ReadKey(true); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBox.Parsing.ParserGenerationIntegrityTest/TestMap.Gbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefan-baumann/ManiaPlanetSharp/e5b95bcd806bf2ebb0ea8776576861ccb6e4cd83/src/ManiaPlanetSharp.GameBox.Parsing.ParserGenerationIntegrityTest/TestMap.Gbx -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | 10 | namespace ManiaPlanetSharp.GameBoxView 11 | { 12 | /// 13 | /// Interaction logic for App.xaml 14 | /// 15 | public partial class App : Application 16 | { 17 | private void Application_Startup(object sender, StartupEventArgs e) 18 | { 19 | if (e.Args?.Length == 1) 20 | { 21 | string path = e.Args[0]; 22 | if (File.Exists(path) && path.ToLowerInvariant().EndsWith(".gbx")) 23 | { 24 | this.MainWindow = new MainWindow(new GameBoxMetadataViewModel(path)); 25 | } 26 | } 27 | 28 | this.MainWindow = this.MainWindow ?? new MainWindow(); 29 | this.MainWindow.Show(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/GameBoxMetadataViewModel.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | using ManiaPlanetSharp.GameBox.MetadataProviders; 3 | using ManiaPlanetSharp.GameBox.Parsing; 4 | using ManiaPlanetSharp.GameBox.Parsing.Chunks; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Collections.ObjectModel; 8 | using System.ComponentModel; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Runtime.CompilerServices; 12 | using System.Text; 13 | using System.Windows; 14 | using System.Windows.Controls; 15 | using System.Windows.Documents; 16 | using System.Windows.Media; 17 | using System.Windows.Media.Imaging; 18 | 19 | namespace ManiaPlanetSharp.GameBoxView 20 | { 21 | public class GameBoxMetadataViewModel 22 | : INotifyPropertyChanged 23 | { 24 | public GameBoxMetadataViewModel() 25 | { } 26 | 27 | public GameBoxMetadataViewModel(string path) 28 | : this() 29 | { 30 | this.Path = path; 31 | this.File = GameBoxFile.Parse(this.Path); 32 | 33 | this.MetadataTreeItems.Add(new FileMetadataTreeNode(this.File)); 34 | 35 | if (this.File.MainClass == ClassId.CGameCtnChallenge) 36 | { 37 | this.FileType = "Map"; 38 | var map = new MapMetadataProvider(this.File); 39 | this.MetadataProvider = map; 40 | this.MetadataTreeItems.Add(new MapMetadataTreeNode(map) { IsExpanded = true }); 41 | } 42 | else if (this.File.MainClass == ClassId.CGameItemModel) 43 | { 44 | this.FileType = "Item/Block"; 45 | var item = new ItemMetadataProvider(this.File); 46 | this.MetadataProvider = item; 47 | this.MetadataTreeItems.Add(new ItemMetadataTreeNode(item) { IsExpanded = true }); 48 | } 49 | else if (this.File.MainClass == ClassId.CGameCtnMacroBlockInfo) 50 | { 51 | this.FileType = "Macroblock"; 52 | var macroblock = new MacroblockMetadataProvider(this.File); 53 | this.MetadataProvider = macroblock; 54 | this.MetadataTreeItems.Add(new MacroblockMetadataTreeNode(macroblock) { IsExpanded = true }); 55 | } 56 | } 57 | 58 | 59 | 60 | public string Path { get; private set; } 61 | 62 | public string FileType { get; private set; } 63 | 64 | public GameBoxFile File { get; private set; } 65 | 66 | public MetadataProvider MetadataProvider { get; private set; } 67 | 68 | 69 | 70 | public string TitleText => $"MP# GameBoxView - {(string.IsNullOrWhiteSpace(this.Path) ? "drag and drop file to open" : this.Path)}"; 71 | 72 | public ObservableCollection MetadataTreeItems { get; private set; } = new ObservableCollection(); 73 | 74 | 75 | 76 | public event PropertyChangedEventHandler PropertyChanged; 77 | 78 | [MethodImpl(MethodImplOptions.NoInlining)] 79 | protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 80 | { 81 | this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | using ManiaPlanetSharp.GameBox.MetadataProviders; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows; 10 | using System.Windows.Controls; 11 | using System.Windows.Data; 12 | using System.Windows.Documents; 13 | using System.Windows.Input; 14 | using System.Windows.Media; 15 | using System.Windows.Media.Imaging; 16 | using System.Windows.Navigation; 17 | using System.Windows.Shapes; 18 | 19 | namespace ManiaPlanetSharp.GameBoxView 20 | { 21 | /// 22 | /// Interaction logic for MainWindow.xaml 23 | /// 24 | public partial class MainWindow : Window 25 | { 26 | public MainWindow() 27 | : this(new GameBoxMetadataViewModel()) 28 | { } 29 | 30 | public MainWindow(GameBoxMetadataViewModel viewModel) 31 | { 32 | InitializeComponent(); 33 | this.DataContext = viewModel; 34 | } 35 | 36 | private void Grid_Drop(object sender, DragEventArgs e) 37 | { 38 | if (e.Data.GetDataPresent(DataFormats.FileDrop)) 39 | { 40 | string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); 41 | if (files?.Length == 1 && files[0].ToLowerInvariant().EndsWith(".gbx")) 42 | { 43 | e.Handled = true; 44 | this.DataContext = new GameBoxMetadataViewModel(files[0]); 45 | GC.Collect(); 46 | } 47 | } 48 | } 49 | 50 | private void Grid_Drag(object sender, DragEventArgs e) 51 | { 52 | e.Effects = DragDropEffects.None; 53 | if (e.Data.GetDataPresent(DataFormats.FileDrop)) 54 | { 55 | string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); 56 | if (files?.Length == 1 && files[0].ToLowerInvariant().EndsWith(".gbx")) 57 | { 58 | e.Effects = DragDropEffects.Copy; 59 | } 60 | } 61 | } 62 | 63 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) 64 | { 65 | try 66 | { 67 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true, Verb = "open" }); 68 | } 69 | catch 70 | { 71 | #if DEBUG 72 | throw; 73 | #endif 74 | } 75 | e.Handled = true; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/ManiaPlanetSharp.GameBoxView.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows 6 | true 7 | Stefan Baumann 8 | Stefan Baumann 9 | Application for viewing metadata from files created with the GameBox engine by Ubisoft Nadeo. 10 | Copyright © 2020 Stefan Baumann 11 | https://github.com/stefan-baumann/ManiaPlanetSharp 12 | https://github.com/stefan-baumann/ManiaPlanetSharp 13 | 1.0.0 14 | 1.0.0 15 | ManiaPlanetSharp.GameBoxView.App 16 | LICENSE 17 | 18 | 19 | 20 | DEBUG;TRACE 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | True 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/RelayCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Text; 5 | using System.Windows.Input; 6 | 7 | namespace ManiaPlanetSharp.GameBoxView 8 | { 9 | /// 10 | /// A command whose sole purpose is to 11 | /// relay its functionality to other 12 | /// objects by invoking delegates. The 13 | /// default return value for the CanExecute 14 | /// method is 'true'. 15 | /// 16 | public class RelayCommand : ICommand 17 | { 18 | #region Fields 19 | 20 | readonly Action _execute; 21 | readonly Predicate _canExecute; 22 | 23 | #endregion // Fields 24 | 25 | #region Constructors 26 | 27 | /// 28 | /// Creates a new command that can always execute. 29 | /// 30 | /// The execution logic. 31 | public RelayCommand(Action execute) 32 | : this(execute, null) 33 | { 34 | } 35 | 36 | /// 37 | /// Creates a new command. 38 | /// 39 | /// The execution logic. 40 | /// The execution status logic. 41 | public RelayCommand(Action execute, Predicate canExecute) 42 | { 43 | _execute = execute ?? throw new ArgumentNullException("execute"); 44 | _canExecute = canExecute; 45 | } 46 | 47 | #endregion // Constructors 48 | 49 | #region ICommand Members 50 | 51 | [DebuggerStepThrough] 52 | public bool CanExecute(object parameters) 53 | { 54 | return _canExecute == null ? true : _canExecute(parameters); 55 | } 56 | 57 | public event EventHandler CanExecuteChanged 58 | { 59 | add { CommandManager.RequerySuggested += value; } 60 | remove { CommandManager.RequerySuggested -= value; } 61 | } 62 | 63 | public void Execute(object parameters) 64 | { 65 | _execute(parameters); 66 | } 67 | 68 | #endregion // ICommand Members 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/DecorationTreeNode.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | using System.Collections.ObjectModel; 3 | 4 | namespace ManiaPlanetSharp.GameBoxView 5 | { 6 | public class DecorationTreeNode 7 | : TextTreeNode 8 | { 9 | public DecorationTreeNode(string name, string timeOfDay, string mappedTimeOfDay, string environment, string environmentAuthor, Size3D? size) 10 | : base(name, $"{timeOfDay} ({environment})") 11 | { 12 | this.TimeOfDay = timeOfDay; 13 | this.MappedTimeOfDay = mappedTimeOfDay; 14 | this.Environment = environment; 15 | this.EnvironmentAuthor = environmentAuthor; 16 | this.Size = size; 17 | 18 | this.HideValueWhenExpanded = true; 19 | 20 | if (!string.IsNullOrWhiteSpace(this.TimeOfDay)) 21 | this.Nodes.Add(new TextTreeNode("Time of day", this.TimeOfDay)); 22 | if (!string.IsNullOrWhiteSpace(this.TimeOfDay)) 23 | this.Nodes.Add(new TextTreeNode("Mapped Time of day", this.MappedTimeOfDay)); 24 | if (this.Size != null) 25 | this.Nodes.Add(new TextTreeNode("Size", $"{this.Size.Value.X}x{this.Size.Value.Y}x{this.Size.Value.Z}") { HideValueWhenExpanded = true, Nodes = new ObservableCollection() 26 | { 27 | new TextTreeNode("X", this.Size.Value.X.ToString()), 28 | new TextTreeNode("Y", this.Size.Value.Y.ToString()), 29 | new TextTreeNode("Z", this.Size.Value.Z.ToString()) 30 | } }); 31 | if (!string.IsNullOrWhiteSpace(this.Environment)) 32 | this.Nodes.Add(new TextTreeNode("Environment", this.Environment)); 33 | if (!string.IsNullOrWhiteSpace(this.EnvironmentAuthor)) 34 | this.Nodes.Add(new TextTreeNode("Environment Author", this.EnvironmentAuthor)); 35 | } 36 | 37 | public string TimeOfDay { get; private set; } 38 | public string MappedTimeOfDay { get; private set; } 39 | public string Environment { get; private set; } 40 | public string EnvironmentAuthor { get; private set; } 41 | public Size3D? Size { get; private set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/DependencyTreeNode.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox.Parsing.Chunks; 2 | 3 | namespace ManiaPlanetSharp.GameBoxView 4 | { 5 | public class DependencyTreeNode 6 | : TextTreeNode 7 | { 8 | public DependencyTreeNode(MapCommunityDependency dependency) 9 | : base($"{System.IO.Path.GetFileName(dependency?.File)} ({(string.IsNullOrWhiteSpace(dependency.Url) ? "local" : "remote")})") 10 | { 11 | this.Dependency = dependency; 12 | if (this.Dependency != null) 13 | { 14 | this.Nodes.Add(new TextTreeNode("Path", dependency.File)); 15 | if (!string.IsNullOrWhiteSpace(dependency.Url)) 16 | this.Nodes.Add(new HyperlinkTreeNode("Url", dependency.Url)); 17 | } 18 | } 19 | 20 | public virtual MapCommunityDependency Dependency { get; private set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/EmbeddedItemTreeNode.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | using ManiaPlanetSharp.GameBox.MetadataProviders; 3 | using ManiaPlanetSharp.GameBox.Parsing.Chunks; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | 7 | namespace ManiaPlanetSharp.GameBoxView 8 | { 9 | public class EmbeddedItemTreeNode 10 | : TextTreeNode 11 | { 12 | public EmbeddedItemTreeNode(EmbeddedItem item, EmbeddedItemFile file) 13 | : base(System.IO.Path.GetFileName(item.Path)) 14 | { 15 | this.Item = item; 16 | this.File = file; 17 | this.Nodes.Add(new TextTreeNode("Path", this.Item.Path)); 18 | this.Nodes.Add(new TextTreeNode("Author", this.Item.Author)); 19 | this.Nodes.Add(new TextTreeNode("Collection", this.Item.Collection)); 20 | var analyzerNode = new ButtonTreeNode("Item File", $"Analyze ({file?.Data?.Length ?? 0} bytes)"); 21 | analyzerNode.ButtonClicked += (s, e) => 22 | { 23 | this.Nodes.Remove(analyzerNode); 24 | var file = this.File.Parse(); 25 | var item = new ItemMetadataProvider(file); 26 | var fileNode = new TextTreeNode("Item File") 27 | { 28 | IsExpanded = true, 29 | Nodes = new ObservableCollection() 30 | { 31 | new FileMetadataTreeNode(file), 32 | new ItemMetadataTreeNode(item) 33 | } 34 | }; 35 | 36 | this.Nodes.Add(fileNode); 37 | }; 38 | this.Nodes.Add(analyzerNode); 39 | } 40 | 41 | public EmbeddedItem Item { get; set; } 42 | public EmbeddedItemFile File { get; set; } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/FileReferenceTreeNode.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | using System.Linq; 3 | 4 | namespace ManiaPlanetSharp.GameBoxView 5 | { 6 | public class FileReferenceTreeNode 7 | : TextTreeNode 8 | { 9 | public FileReferenceTreeNode(string name, FileReference value) 10 | : base(name) 11 | { 12 | this.Reference = value; 13 | 14 | if (this.Reference != null && !string.IsNullOrWhiteSpace(this.Reference.FilePath)) 15 | { 16 | this.Nodes.Add(new TextTreeNode("Path", $"{this.Reference.FilePath}{(this.Reference.IsRelativePath ? " (relative)" : "")}")); 17 | this.Nodes.Add(new HyperlinkTreeNode("Url", this.Reference.LocatorUrl)); 18 | this.Nodes.Add(new TextTreeNode("Checksum", string.Join("", this.Reference.Checksum.Select(b => b.ToString("X2"))))); 19 | } 20 | } 21 | 22 | public FileReference Reference { get; private set; } 23 | 24 | public override string Value => System.IO.Path.GetFileName(this.Reference?.FilePath) ?? "None"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/PlayerTreeNode.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.GameBoxView 2 | { 3 | public class PlayerTreeNode 4 | : FormattedTextTreeNode 5 | { 6 | public PlayerTreeNode(string name, string nickname, string login, string zone) 7 | : base(name, nickname) 8 | { 9 | this.Nickname = nickname; 10 | this.Login = login; 11 | this.Zone = zone; 12 | 13 | this.HideValueWhenExpanded = true; 14 | 15 | if (!string.IsNullOrWhiteSpace(this.Nickname)) 16 | this.Nodes.Add(new FormattedTextTreeNode("Nickname", this.Nickname)); 17 | if (!string.IsNullOrWhiteSpace(this.Login)) 18 | this.Nodes.Add(new TextTreeNode("Login", this.Login)); 19 | if (!string.IsNullOrWhiteSpace(this.Zone)) 20 | this.Nodes.Add(new TextTreeNode("Zone", this.Zone)); 21 | } 22 | 23 | public string Nickname { get; private set; } 24 | public string Login { get; private set; } 25 | public string Zone { get; private set; } 26 | 27 | public override string FormattedText => this.Nickname ?? "None"; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/ReferenceTableFolderTreeNode.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | using System.Collections.ObjectModel; 3 | using System.Linq; 4 | 5 | namespace ManiaPlanetSharp.GameBoxView 6 | { 7 | public class ReferenceTableFolderTreeNode 8 | : TextTreeNode 9 | { 10 | public ReferenceTableFolderTreeNode(ReferenceTableFolder rtf) 11 | : base(rtf.Name, $"{rtf.SubFolders.Length} subfolders") 12 | { 13 | this.ReferenceTableFolder = rtf; 14 | if (this.ReferenceTableFolder.SubFolders.Length > 0) 15 | { 16 | this.Nodes = new ObservableCollection(this.ReferenceTableFolder.SubFolders.Select(rtf => new ReferenceTableFolderTreeNode(rtf))); 17 | } 18 | } 19 | public virtual ReferenceTableFolder ReferenceTableFolder { get; private set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/ReferenceTableTreeNode.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | 3 | namespace ManiaPlanetSharp.GameBoxView 4 | { 5 | public class ReferenceTableTreeNode 6 | : TextTreeNode 7 | { 8 | public ReferenceTableTreeNode(ReferenceTableExternalNode node) 9 | : base(node.FileName) 10 | { 11 | this.Node = node; 12 | 13 | //this.HideValueWhenExpanded = true; 14 | 15 | if (!string.IsNullOrWhiteSpace(this.Node?.FileName)) 16 | new TextTreeNode("File Name", this.Node.FileName); 17 | new TextTreeNode("Resource Index", this.Node.ResourceIndex.ToString()); 18 | new TextTreeNode("Node Index", this.Node.NodeIndex.ToString()); 19 | new TextTreeNode("Folder Index", this.Node.FolderIndex.ToString()); 20 | new TextTreeNode("Use File", this.Node.UseFile ? "True" : "False"); 21 | } 22 | 23 | public ReferenceTableExternalNode Node { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/TimeTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace ManiaPlanetSharp.GameBoxView 5 | { 6 | public class TimeTreeNode 7 | : TextTreeNode 8 | { 9 | public TimeTreeNode(string name, TimeSpan? time) 10 | : base(name) 11 | { 12 | this.Time = time; 13 | } 14 | 15 | public virtual TimeSpan? Time { get; private set; } 16 | 17 | public override string Value => Regex.Replace(this.Time?.ToString() ?? "None", @"(^(00:){0,2})|((?<=\d{3})0+$)", ""); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/TimesTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ManiaPlanetSharp.GameBoxView 4 | { 5 | public class TimesTreeNode 6 | : TimeTreeNode 7 | { 8 | public TimesTreeNode(string name, TimeSpan? author, int? score, TimeSpan? gold, TimeSpan? silver, TimeSpan? bronze) 9 | : base(name, author) 10 | { 11 | this.Author = author; 12 | this.Score = score; 13 | this.Gold = gold; 14 | this.Silver = silver; 15 | this.Bronze = bronze; 16 | 17 | this.HideValueWhenExpanded = true; 18 | 19 | this.Nodes.Add(new TimeTreeNode("Author Time", this.Author)); 20 | this.Nodes.Add(new TextTreeNode("Author Score", $"{this.Score?.ToString() ?? "no"} points")); 21 | this.Nodes.Add(new TimeTreeNode("Gold Time", this.Gold)); 22 | this.Nodes.Add(new TimeTreeNode("Silver Time", this.Silver)); 23 | this.Nodes.Add(new TimeTreeNode("Bronze Time", this.Bronze)); 24 | } 25 | 26 | public virtual TimeSpan? Author { get; private set; } 27 | public virtual int? Score { get; private set; } 28 | public virtual TimeSpan? Gold { get; private set; } 29 | public virtual TimeSpan? Silver { get; private set; } 30 | public virtual TimeSpan? Bronze { get; private set; } 31 | 32 | public override TimeSpan? Time => this.Author; 33 | 34 | 35 | public override string Value => $"{base.Value} ({this.Score?.ToString() ?? "no"} points)"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Advanced/VehicleTreeNode.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.GameBoxView 2 | { 3 | public class VehicleTreeNode 4 | : TextTreeNode 5 | { 6 | public VehicleTreeNode(string name, string vehicle, string author, string collection) 7 | : base(name) 8 | { 9 | this.Vehicle = vehicle; 10 | this.Author = author; 11 | this.Collection = collection; 12 | 13 | if (!string.IsNullOrWhiteSpace(this.Vehicle)) 14 | { 15 | this.HideValueWhenExpanded = true; 16 | this.Nodes.Add(new TextTreeNode("Name", this.Vehicle)); 17 | if (!string.IsNullOrWhiteSpace(this.Author)) 18 | this.Nodes.Add(new TextTreeNode("Author", this.Author)); 19 | if (!string.IsNullOrWhiteSpace(this.Collection)) 20 | this.Nodes.Add(new TextTreeNode("Collection", this.Collection)); 21 | } 22 | } 23 | 24 | public virtual string Vehicle { get; private set; } 25 | public virtual string Author { get; private set; } 26 | public virtual string Collection { get; private set; } 27 | 28 | public override string Value => !string.IsNullOrWhiteSpace(this.Vehicle) ? this.Vehicle : "Default"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/ButtonTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | namespace ManiaPlanetSharp.GameBoxView 5 | { 6 | public class ButtonTreeNode 7 | : TextTreeNode 8 | { 9 | public ButtonTreeNode(string name, string value) 10 | : base(name, value) 11 | { } 12 | 13 | private ICommand buttonClickCommand; 14 | 15 | public ICommand ButtonClickCommand => this.buttonClickCommand ?? (this.buttonClickCommand = new RelayCommand(_ => this.OnButtonClicked())); 16 | 17 | public event EventHandler ButtonClicked; 18 | public virtual void OnButtonClicked() 19 | { 20 | this.ButtonClicked?.Invoke(this, EventArgs.Empty); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/HyperlinkTreeNode.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.GameBoxView 2 | { 3 | public class HyperlinkTreeNode 4 | : TextTreeNode 5 | { 6 | public HyperlinkTreeNode(string name, string url) 7 | : this(name, url, url) 8 | { } 9 | 10 | public HyperlinkTreeNode(string name, string text, string url) 11 | : base(name, text) 12 | { 13 | this.Url = url; 14 | } 15 | 16 | public virtual string Url { get; private set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/ImageTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | 4 | namespace ManiaPlanetSharp.GameBoxView 5 | { 6 | public class ImageTreeNode 7 | : TextTreeNode 8 | { 9 | public ImageTreeNode(ImageSource imageSource, Size size) 10 | : base(null) 11 | { 12 | this.ImageSource = imageSource; 13 | this.Size = size; 14 | } 15 | 16 | public virtual ImageSource ImageSource { get; private set; } 17 | 18 | public Size Size { get; private set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Metadata/EmbeddedMapTreeNode.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | using ManiaPlanetSharp.GameBox.MetadataProviders; 3 | using System.Collections.Generic; 4 | 5 | namespace ManiaPlanetSharp.GameBoxView.TreeNodes.Advanced 6 | { 7 | public class EmbeddedMapTreeNode : 8 | MetadataTreeNode 9 | { 10 | public EmbeddedMapTreeNode(string name, GameBoxFile file): 11 | base(name) 12 | { 13 | this.File = file; 14 | this.InitializeNodes(); 15 | } 16 | 17 | public GameBoxFile File { get; private set; } 18 | 19 | protected override IEnumerable GetNodes() 20 | { 21 | var provider = new MapMetadataProvider(File); 22 | yield return new MapMetadataTreeNode(provider); 23 | yield return new FileMetadataTreeNode(File); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Metadata/MacroblockMetadataTreeNode.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox.MetadataProviders; 2 | using ManiaPlanetSharp.GameBox.Parsing.Chunks; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.Drawing; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Windows; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | 14 | namespace ManiaPlanetSharp.GameBoxView 15 | { 16 | public class MacroblockMetadataTreeNode 17 | : MetadataTreeNode 18 | { 19 | private const string NotAvailable = "not available"; 20 | 21 | public MacroblockMetadataTreeNode(MacroblockMetadataProvider macroblock) 22 | : base("Macroblock Metadata") 23 | { 24 | this.Macroblock = macroblock; 25 | this.InitializeNodes(); 26 | } 27 | 28 | public MacroblockMetadataProvider Macroblock { get; private set; } 29 | 30 | protected override IEnumerable GetNodes() 31 | { 32 | yield return new FormattedTextTreeNode("Name", this.Macroblock.Name ?? NotAvailable); 33 | yield return new FormattedTextTreeNode("Description", string.IsNullOrWhiteSpace(this.Macroblock.Description) ? "no description" : this.Macroblock.Description); 34 | yield return new FormattedTextTreeNode("Author", string.IsNullOrWhiteSpace(this.Macroblock.Author) ? NotAvailable : this.Macroblock.Author); 35 | 36 | yield return new TextTreeNode("Collection", this.Macroblock.Collection ?? NotAvailable); 37 | yield return new TextTreeNode("Path", this.Macroblock.Path ?? NotAvailable); 38 | 39 | var icon = this.Macroblock.GenerateIconBitmap(); 40 | if (icon != null) 41 | { 42 | var image = this.ImageSourceFromImage(this.Macroblock.GenerateIconBitmap()); 43 | yield return new TextTreeNode("Icon", $"{image.Width:#0}x{image.Height:#0}") 44 | { 45 | HideValueWhenExpanded = true, 46 | Nodes = new ObservableCollection() 47 | { 48 | new ImageTreeNode(image, new System.Windows.Size(image.Width, image.Height)), 49 | new TextTreeNode("Size", $"{image.Width:#0}x{image.Height:#0}"), 50 | new TextTreeNode("Auto-Generated", this.Macroblock.UseAutoRenderedIcon != null ? this.Macroblock.UseAutoRenderedIcon.Value ? "True" : "False" : NotAvailable), 51 | new TextTreeNode("Icon Quarter-Rotations", this.Macroblock.IconQuarterRotations?.ToString() ?? NotAvailable) 52 | } 53 | }; 54 | } 55 | else 56 | { 57 | yield return new TextTreeNode("Icon", "no icon"); 58 | } 59 | 60 | yield return new TextTreeNode("Product State", this.Macroblock.ProductState?.ToString() ?? NotAvailable); 61 | 62 | yield break; 63 | } 64 | 65 | protected ImageSource ImageSourceFromImage(System.Drawing.Image source) 66 | { 67 | using var ms = new MemoryStream(); 68 | source.Save(ms, System.Drawing.Imaging.ImageFormat.Png); 69 | ms.Position = 0; 70 | 71 | var bi = new BitmapImage(); 72 | bi.BeginInit(); 73 | bi.CacheOption = BitmapCacheOption.OnLoad; 74 | bi.StreamSource = ms; 75 | bi.EndInit(); 76 | 77 | return bi; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/Metadata/MetadataTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Text; 5 | 6 | namespace ManiaPlanetSharp.GameBoxView 7 | { 8 | public abstract class MetadataTreeNode 9 | : TextTreeNode 10 | { 11 | protected MetadataTreeNode(string name) 12 | : base(name) 13 | { } 14 | 15 | protected void InitializeNodes() 16 | { 17 | this.Nodes = new ObservableCollection(this.GetNodes().CatchExceptions()); 18 | } 19 | 20 | protected abstract IEnumerable GetNodes(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeNodes/TextTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | using System.Windows; 5 | using System.Windows.Input; 6 | 7 | namespace ManiaPlanetSharp.GameBoxView 8 | { 9 | public class TextTreeNode 10 | : INotifyPropertyChanged 11 | { 12 | public TextTreeNode(string name) 13 | { 14 | this.Name = name; 15 | } 16 | 17 | public TextTreeNode(string name, string value) 18 | : this(name) 19 | { 20 | this.Value = value; 21 | } 22 | 23 | public virtual string Name { get; private set; } 24 | 25 | private string value; 26 | public virtual string Value 27 | { 28 | get => this.value; 29 | private set 30 | { 31 | this.value = value; 32 | this.OnPropertyChanged(); 33 | } 34 | } 35 | 36 | public string DisplayText => this.HideValueWhenExpanded && this.IsExpanded ? null : this.Value; 37 | 38 | public bool HasValue => !string.IsNullOrWhiteSpace(this.Value); 39 | 40 | private bool hideValueWhenExpanded = false; 41 | public bool HideValueWhenExpanded 42 | { 43 | get { return this.hideValueWhenExpanded; } 44 | set 45 | { 46 | if (value != this.hideValueWhenExpanded) 47 | { 48 | this.hideValueWhenExpanded = value; 49 | this.OnPropertyChanged(); 50 | } 51 | } 52 | } 53 | 54 | public virtual string Tooltip { get; private set; } 55 | 56 | public bool HasTooltip => !string.IsNullOrWhiteSpace(this.Tooltip); 57 | 58 | 59 | private bool isSelected = false; 60 | public virtual bool IsSelected 61 | { 62 | get { return this.isSelected; } 63 | set 64 | { 65 | if (value != this.isSelected) 66 | { 67 | this.isSelected = value; 68 | this.OnPropertyChanged(); 69 | } 70 | } 71 | } 72 | 73 | private bool isExpanded = false; 74 | 75 | public virtual bool IsExpanded 76 | { 77 | get { return this.isExpanded; } 78 | set 79 | { 80 | if (value != this.isExpanded) 81 | { 82 | this.isExpanded = value; 83 | this.OnPropertyChanged(); 84 | 85 | if (this.HideValueWhenExpanded) 86 | { 87 | this.OnPropertyChanged("Value"); 88 | this.OnPropertyChanged("HasValue"); 89 | } 90 | } 91 | } 92 | } 93 | 94 | 95 | 96 | private ICommand copyCommand; 97 | 98 | public ICommand CopyCommand => this.copyCommand ?? (this.copyCommand = new RelayCommand(_ => this.OnCopy())); 99 | public virtual void OnCopy() 100 | { 101 | Clipboard.SetText(this.GenerateCopyString()); 102 | } 103 | 104 | protected virtual string GenerateCopyString() 105 | { 106 | return this.Value; 107 | } 108 | 109 | 110 | 111 | public virtual ObservableCollection Nodes { get; set; } = new ObservableCollection(); 112 | 113 | public event PropertyChangedEventHandler PropertyChanged; 114 | 115 | [MethodImpl(MethodImplOptions.NoInlining)] 116 | protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 117 | { 118 | this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 119 | if (propertyName == "Value") 120 | { 121 | this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("DisplayText")); 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/TreeViewItemHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using System.Windows.Input; 7 | 8 | namespace ManiaPlanetSharp.GameBoxView 9 | { 10 | public static class TreeViewItemHelper 11 | { 12 | private static TreeViewItem CurrentItem; 13 | private static readonly RoutedEvent UpdateOverItemEvent = EventManager.RegisterRoutedEvent("UpdateOverItem", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TreeViewItemHelper)); 14 | private static readonly DependencyPropertyKey IsMouseDirectlyOverItemKey = DependencyProperty.RegisterAttachedReadOnly("IsMouseDirectlyOverItem", typeof(bool), typeof(TreeViewItemHelper), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CalculateIsMouseDirectlyOverItem))); 15 | public static readonly DependencyProperty IsMouseDirectlyOverItemProperty = IsMouseDirectlyOverItemKey.DependencyProperty; 16 | 17 | static TreeViewItemHelper() 18 | { 19 | EventManager.RegisterClassHandler(typeof(TreeViewItem), UIElement.MouseEnterEvent, new MouseEventHandler(OnMouseTransition), true); 20 | EventManager.RegisterClassHandler(typeof(TreeViewItem), UIElement.MouseLeaveEvent, new MouseEventHandler(OnMouseTransition), true); 21 | EventManager.RegisterClassHandler(typeof(TreeViewItem), UpdateOverItemEvent, new RoutedEventHandler(OnUpdateOverItem)); 22 | } 23 | public static bool GetIsMouseDirectlyOverItem(DependencyObject obj) 24 | { 25 | return (bool)obj.GetValue(IsMouseDirectlyOverItemProperty); 26 | } 27 | private static object CalculateIsMouseDirectlyOverItem(DependencyObject item, object value) 28 | { 29 | return item == CurrentItem; 30 | } 31 | private static void OnUpdateOverItem(object sender, RoutedEventArgs e) 32 | { 33 | CurrentItem = sender as TreeViewItem; 34 | CurrentItem.InvalidateProperty(IsMouseDirectlyOverItemProperty); 35 | e.Handled = true; 36 | } 37 | private static void OnMouseTransition(object sender, MouseEventArgs e) 38 | { 39 | lock (IsMouseDirectlyOverItemProperty) 40 | { 41 | if (CurrentItem != null) 42 | { 43 | DependencyObject oldItem = CurrentItem; 44 | CurrentItem = null; 45 | oldItem.InvalidateProperty(IsMouseDirectlyOverItemProperty); 46 | } 47 | 48 | Mouse.DirectlyOver?.RaiseEvent(new RoutedEventArgs(UpdateOverItemEvent)); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.GameBoxView/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBoxView 6 | { 7 | public static class Utils 8 | { 9 | public static IEnumerable CatchExceptions(this IEnumerable src, Action handler = null) 10 | { 11 | using (var enumerator = src.GetEnumerator()) 12 | { 13 | bool next = true; 14 | 15 | while (next) 16 | { 17 | try 18 | { 19 | next = enumerator.MoveNext(); 20 | } 21 | catch (Exception ex) 22 | { 23 | handler?.Invoke(ex); 24 | continue; 25 | } 26 | 27 | if (next) 28 | yield return enumerator.Current; 29 | } 30 | } 31 | 32 | yield break; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.ParserTest/ManiaPlanetSharp.ParserTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0-windows7.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp.ParserTest/Program.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | using ManiaPlanetSharp.GameBox.MetadataProviders; 3 | using ManiaPlanetSharp.GameBox.Parsing; 4 | using ManiaPlanetSharp.GameBox.Parsing.Chunks; 5 | using System; 6 | using System.Diagnostics; 7 | using System.IO; 8 | using System.Linq; 9 | 10 | namespace ManiaPlanetSharp.ParserTest 11 | { 12 | public static class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | //Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); 17 | 18 | ParserFactory.InitializePrecompiledParsers(); 19 | while (true) 20 | { 21 | Console.Write("GameBox file: "); 22 | string path = Console.ReadLine(); 23 | if (path.StartsWith("\"") && path.EndsWith("\"")) 24 | { 25 | path = path[1..^1]; 26 | } 27 | if (File.Exists(path)) 28 | { 29 | using MemoryStream stream = new MemoryStream(File.ReadAllBytes(path)); 30 | try 31 | { 32 | Stopwatch stopwatch = Stopwatch.StartNew(); 33 | GameBoxFile file = GameBoxFile.Parse(stream); 34 | double headerTime = stopwatch.Elapsed.TotalMilliseconds; 35 | var chunks = file.ParseBody(); 36 | stopwatch.Stop(); 37 | 38 | //Create metadata provider and parse body with disabled console output 39 | //var console = Console.Out; 40 | //Console.SetOut(TextWriter.Null); 41 | var metadataProvider = new MapMetadataProvider(file); 42 | metadataProvider.ParseBody(); 43 | //Console.SetOut(console); 44 | 45 | Console.WriteLine("Metadata:"); 46 | foreach (var property in metadataProvider.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).Where(property => property.Name != "File")) 47 | { 48 | Console.WriteLine($" - {property.Name}: {property.GetValue(metadataProvider)}"); 49 | } 50 | 51 | Console.WriteLine($"Done in {stopwatch.Elapsed.TotalMilliseconds:#0.0}ms (header: {headerTime:#0.0}ms, body: {stopwatch.Elapsed.TotalMilliseconds - headerTime:#0.0}ms)."); 52 | } 53 | catch (ParseException ex) 54 | { 55 | Console.WriteLine(ex.Message); 56 | Console.WriteLine(ex.InnerException.ToString()); 57 | } 58 | } 59 | else 60 | { 61 | Console.WriteLine("Could not find the specified file."); 62 | } 63 | Console.WriteLine(new string('-', Console.WindowWidth / 2)); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Chunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox 6 | { 7 | /// 8 | /// Base class for chunks. 9 | /// 10 | public abstract class Chunk 11 | : Node 12 | { } 13 | 14 | /// 15 | /// Special class for chunks of unknown type. 16 | /// 17 | public class UnknownChunk 18 | : Chunk 19 | { 20 | /// 21 | /// Creates a new instance of the UnknownChunk type. 22 | /// 23 | /// The raw data of the unknown chunk. 24 | /// The chunk id of the unknown chunk. 25 | public UnknownChunk(byte[] data, uint chunkId) 26 | : this(data) 27 | { 28 | this.Id = chunkId; 29 | } 30 | 31 | /// 32 | /// Creates a new instance of the UnknownChunk type. 33 | /// 34 | /// The raw data of the unknown chunk. 35 | public UnknownChunk(byte[] data) 36 | { 37 | this.Data = data; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/MetadataProviders/ItemMetadataProvider.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox.Parsing.Chunks; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace ManiaPlanetSharp.GameBox.MetadataProviders 8 | { 9 | public class ItemMetadataProvider 10 | : CollectorMetadataProvider 11 | { 12 | public ItemMetadataProvider(GameBoxFile file) 13 | : base(file) 14 | { } 15 | 16 | 17 | public virtual ObjectType? Type => this.GetBufferedHeaderValue((ObjectItemTypeChunk c) => c?.ItemType); 18 | 19 | public virtual Vector3D? GroundPoint => this.GetBufferedBodyValue((ObjectGroundPointChunk c) => c?.GroundPoint); 20 | 21 | public virtual float? PainterGroundMargin => this.GetBufferedBodyValue((ObjectGroundPointChunk c) => c?.PainterGroundMargin); 22 | 23 | public virtual float? OrbitalCenterHeightFromGround => this.GetBufferedBodyValue((ObjectGroundPointChunk c) => c?.OrbitalCenterHeightFromGround); 24 | 25 | public virtual float? OrbitalRadiusBase => this.GetBufferedBodyValue((ObjectGroundPointChunk c) => c?.OrbitalRadiusBase); 26 | 27 | public virtual float? OrbitalPreviewAngle => this.GetBufferedBodyValue((ObjectGroundPointChunk c) => c?.OrbitalPreviewAngle); 28 | 29 | public virtual string MeshName => this.GetBufferedBodyValue((ObjectModelChunk c) => c.MeshName) 30 | .IgnoreIfEmpty(); 31 | 32 | public virtual string ShapeName => this.GetBufferedBodyValue((ObjectModelChunk c) => c.ShapeName) 33 | .IgnoreIfEmpty(); 34 | 35 | public virtual string TriggerShapeName => this.GetBufferedBodyValue((ObjectModelChunk c) => c.TriggerShapeName) 36 | .IgnoreIfEmpty(); 37 | } 38 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/MetadataProviders/MacroBlockMetadataProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.MetadataProviders 6 | { 7 | public class MacroblockMetadataProvider 8 | : CollectorMetadataProvider 9 | { 10 | public MacroblockMetadataProvider(GameBoxFile file) 11 | : base(file) 12 | { } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Node.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Text; 6 | 7 | namespace ManiaPlanetSharp.GameBox 8 | { 9 | /// 10 | /// Base class for all nodes and chunks. 11 | /// 12 | public abstract class Node 13 | { 14 | /// 15 | /// Creates a new empty instance of the Node class. 16 | /// 17 | protected Node() 18 | { } 19 | 20 | /// 21 | /// Creates a new empty instance of the Node class with a specified id. 22 | /// 23 | /// The engine id of this node. 24 | protected Node(uint id) 25 | : this() 26 | { 27 | this.Id = id; 28 | } 29 | 30 | 31 | /// 32 | /// Creates a new instance of the Node class with a specified id. 33 | /// 34 | /// The engine id of this node. 35 | /// The raw data of this node. 36 | protected Node(uint id, byte[] data) 37 | : this(id) 38 | { 39 | this.Data = data; 40 | } 41 | 42 | 43 | 44 | /// 45 | /// The full id of this node. 46 | /// 47 | public virtual uint Id { get; set; } 48 | 49 | /// 50 | /// The class part of the id of this node. 51 | /// 52 | public virtual uint ClassId => this.Id & 0xFFFFF000; 53 | 54 | /// 55 | /// The chunk part of the id of this node. 56 | /// 57 | public virtual uint ChunkId => this.Id & 0xFFF; 58 | 59 | /// 60 | /// The raw data of this node. 61 | /// 62 | public byte[] Data { get; set; } 63 | 64 | 65 | 66 | /// 67 | /// Returns the class name associated with this node's class id. 68 | /// 69 | /// 70 | public virtual string GetClassName() 71 | { 72 | return GameBox.ClassIds.GetClassName(this.ClassId); 73 | } 74 | 75 | /// 76 | /// Creates a MemoryStream with the raw data of this node. 77 | /// 78 | /// 79 | public virtual Stream GetStream() 80 | { 81 | return new MemoryStream(this.Data ?? throw new NullReferenceException("This node does not have any stored data.")); 82 | } 83 | 84 | /// 85 | /// Returns a string that represents the current node. 86 | /// 87 | public override string ToString() 88 | { 89 | if (ClassIds.TryMapToNewEngine(this.Id, out uint mappedId)) 90 | { 91 | return $"{this.GetType().Name} (0x{this.Id:X8} -> 0x{mappedId:X8}/{this.GetClassName()})"; 92 | } 93 | else 94 | { 95 | return $"{this.GetType().Name} (0x{this.Id:X8}/{this.GetClassName()})"; 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/ParseException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox 6 | { 7 | /// 8 | /// Wrapper exception for exceptions that occur while parsing. 9 | /// 10 | public class ParseException 11 | : Exception 12 | { 13 | public ParseException(Exception innerException) 14 | : base("An internal error occured while trying to parse the gbx file", innerException) 15 | { } 16 | 17 | public ParseException() 18 | : base() 19 | { } 20 | 21 | public ParseException(string message) 22 | : base(message) 23 | { } 24 | 25 | public ParseException(string message, Exception innerException) 26 | : base(message, innerException) 27 | { } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorBasicMetadataChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E00100B)] 8 | public class CollectorBasicMetadataChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.LookbackString)] 12 | public string Name { get; set; } 13 | 14 | [Property(SpecialPropertyType.LookbackString)] 15 | public string Collection { get; set; } 16 | 17 | [Property(SpecialPropertyType.LookbackString)] 18 | public string Author { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorBrowserMetadataChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E001009)] 8 | public class CollectorBrowserMetadataChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public string PagePath { get; set; } 13 | 14 | [Property] 15 | public bool HasIconFid { get; set; } 16 | 17 | [Property, Condition(nameof(HasIconFid))] 18 | public FileReference Icon { get; set; } //Potentially a NodeRef 19 | 20 | [Property(SpecialPropertyType.LookbackString)] 21 | public string Unused { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorCatalogChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E001007)] 8 | public class CollectorCatalogChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public bool IsInternal { get; set; } 13 | 14 | [Property] 15 | public uint Unused1 { get; set; } 16 | 17 | [Property] 18 | public uint CatalogPosition { get; set; } 19 | 20 | [Property] 21 | public uint Unused2 { get; set; } 22 | 23 | [Property] 24 | public uint Unused3 { get; set; } 25 | 26 | [Property] 27 | public uint Unused4 { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorDefaultSkinChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E00100F)] 8 | public class CollectorDefaultSkinChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public string DefaultSkinName { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorDescriptionChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E00100D)] 8 | public class CollectorDescriptionChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public string Description { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorIconChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Text; 6 | 7 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 8 | { 9 | [Chunk(0x2E001004)] 10 | public class CollectorIconChunk 11 | : Chunk 12 | { 13 | [Property] 14 | public byte Width { get; set; } 15 | 16 | [Property] 17 | public byte Unknown1 { get; set; } 18 | 19 | [Property] 20 | public byte Height { get; set; } 21 | 22 | [Property] 23 | public byte Unknown2 { get; set; } 24 | 25 | public byte[] Padding { get; set; } 26 | 27 | public Size Size => new Size(this.Width, this.Height); 28 | 29 | public int IconSize => this.Width * this.Height * 4; 30 | 31 | [Property, CustomParserMethod(nameof(ReadIconData))] 32 | public byte[] IconData { get; set; } //RGBA 32bpp or WebP 33 | 34 | public byte[] ReadIconData(GameBoxReader reader) 35 | { 36 | if (reader == null) 37 | { 38 | throw new ArgumentNullException(nameof(reader)); 39 | } 40 | 41 | // Both of these are 0 for the old, uncompressed collector images, and 128 for the new webp ones 42 | if (this.Unknown1 == 0 && this.Unknown2 == 0) 43 | { 44 | return reader.ReadRaw(this.IconSize); 45 | } 46 | 47 | if (this.Unknown1 != 128 || this.Unknown2 != 128) 48 | { 49 | Console.WriteLine($"Unknown collector image flag values {{ {this.Unknown1}, {this.Unknown2} }}. Attempting to parse a WebP icon..."); 50 | } 51 | 52 | // Parse WebP data 53 | // There are some bytes before the typical WebP header starts, just search for the magic string and skip forwards to it. 54 | var remainingDataStart = reader.Stream.Position; 55 | var offset = 0; 56 | for (int i = 0; reader.Stream.Length - reader.Stream.Position - 4 > 0; i++) 57 | { 58 | reader.Stream.Position = remainingDataStart + i; 59 | uint u = reader.ReadUInt32(); 60 | if (u == 0x46464952) // "RIFF" 61 | { 62 | offset = i; 63 | break; 64 | } 65 | } 66 | 67 | // Read the actual WebP data 68 | reader.Stream.Position = remainingDataStart + offset; 69 | int length = (int)(reader.Stream.Length - reader.Stream.Position); 70 | return reader.ReadRaw(length); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorIconMetadataChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E00100E)] 8 | public class CollectorIconMetadataChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public bool UseAutoRenderedIcon { get; set; } 13 | 14 | [Property] 15 | public uint QuarterRotationY { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorLightmapCacheIdChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E001006)] 8 | public class CollectorLightmapCacheIdChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public ulong FileTime { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorListChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x0301B000)] 8 | public class CollectorListChunk 9 | : Chunk 10 | { 11 | [Property, Array] 12 | public CollectorStock[] Archive { get; set; } 13 | } 14 | 15 | [CustomStruct] 16 | public class CollectorStock 17 | { 18 | [Property(SpecialPropertyType.LookbackString)] 19 | public string BlockName { get; set; } 20 | [Property(SpecialPropertyType.LookbackString)] 21 | 22 | public string Collection { get; set; } 23 | [Property(SpecialPropertyType.LookbackString)] 24 | 25 | public string Author { get; set; } 26 | 27 | [Property] 28 | public uint Data { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorMetadataChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E001003)] 8 | public class CollectorMetadataChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.LookbackString)] 12 | public string Name { get; set; } 13 | 14 | [Property(SpecialPropertyType.LookbackString)] 15 | public string Collection { get; set; } 16 | 17 | [Property(SpecialPropertyType.LookbackString)] 18 | public string Author { get; set; } 19 | 20 | [Property] 21 | public uint Version { get; set; } 22 | 23 | [Property] 24 | public string Path { get; set; } 25 | 26 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.Equal, 5)] 27 | public string Unused1 { get; set; } 28 | 29 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 4)] 30 | public string Unused2 { get; set; } 31 | 32 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 3)] 33 | public uint Unused3 { get; set; } 34 | 35 | //public uint IsInternal { get; set; } 36 | //public uint IsAdvanced { get; set; } 37 | //public uint IconDescription { get; set; } 38 | //public uint Unused4 { get; set; } 39 | 40 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 4)] 41 | public ushort CatalogPosition { get; set; } 42 | 43 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 7)] 44 | public string Name2 { get; set; } 45 | 46 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 8)] 47 | public byte ProductStateB { get; set; } 48 | public ProductState ProductState => (ProductState)this.ProductStateB; 49 | } 50 | 51 | public enum ProductState 52 | : byte 53 | { 54 | Aborted = 0, 55 | GameBox = 1, 56 | DevelopmentBuild = 2, 57 | Release = 3 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Collector/CollectorNameChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E00100C)] 8 | public class CollectorNameChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public string Name { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostCheckpointEntriesChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 4 | { 5 | [CustomStruct] 6 | public class CheckpointEntry 7 | { 8 | [Property] 9 | public uint TimeU { get; set; } 10 | 11 | public TimeSpan Time { get => TimeSpan.FromMilliseconds(TimeU); } 12 | 13 | [Property] 14 | public uint Flags { get; set; } 15 | } 16 | 17 | [Chunk(0x0309200B, Skippable = true)] 18 | public class GhostCheckpointEntriesChunk 19 | : Chunk 20 | { 21 | [Property, Array] 22 | public CheckpointEntry[] CheckpointEntries { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.IO; 5 | using System.Text; 6 | using System.Xml.Serialization; 7 | 8 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 9 | { 10 | [Chunk(0x03092019)] 11 | public class GhostChunk 12 | : Chunk 13 | { 14 | [Property] 15 | public uint EventsDuration { get; set; } 16 | 17 | [Property, Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 18 | public uint Ignored { get; set; } 19 | 20 | [Property(SpecialPropertyType.LookbackString), Array, Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 21 | public string[] ControlNames { get; set; } 22 | 23 | [Property] 24 | [EditorBrowsable(EditorBrowsableState.Never), Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 25 | public uint ControlEntryCount { get; set; } 26 | 27 | [Property, Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 28 | public uint Unknown { get; set; } 29 | 30 | [Property, Array(nameof(ControlEntryCount)), Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 31 | public GhostControlEntry[] ControlEntries { get; set; } 32 | 33 | [Property(SpecialPropertyType.LongString), Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 34 | public string GameVersion { get; set; } 35 | 36 | [Property, Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 37 | public uint ExecutableChecksum { get; set; } 38 | 39 | [Property, Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 40 | public uint OSKind { get; set; } 41 | 42 | [Property, Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 43 | public uint CPUKind { get; set; } 44 | 45 | private string raceSettingsXmlString; 46 | [Property, Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 47 | public string RaceSettingsXmlString 48 | { 49 | get 50 | { 51 | return this.raceSettingsXmlString; 52 | } 53 | set 54 | { 55 | this.raceSettingsXmlString = value; 56 | //XmlSerializer serializer = new XmlSerializer(typeof(GhostRaceSettingsRoot)); 57 | //using (StringReader stringReader = new StringReader(this.raceSettingsXmlString.Replace("&", "&"))) 58 | //{ 59 | // this.Root = (GhostRaceSettingsRoot)serializer.Deserialize(stringReader); 60 | //} 61 | } 62 | } 63 | 64 | //public GhostRaceSettingsRoot Root { get; set; } 65 | 66 | [Property, Condition(nameof(EventsDuration), ConditionOperator.GreaterThan, 0)] 67 | public uint Unknown2 { get; set; } 68 | } 69 | 70 | [CustomStruct] 71 | public class GhostControlEntry 72 | { 73 | [Property] 74 | public uint TimeU { get; set; } 75 | 76 | public TimeSpan Time => TimeSpan.FromMilliseconds(this.TimeU - 100000); 77 | 78 | [Property] 79 | public byte ControlNameIndex { get; set; } 80 | 81 | [Property] 82 | public uint OnOffU { get; set; } 83 | 84 | public bool OnOff => this.OnOffU > 0; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostDataChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 7 | { 8 | [Chunk(0x0303F005)] 9 | public class GhostDataChunk 10 | : Chunk 11 | { 12 | [Property] 13 | public uint UncompressedSize { get; set; } 14 | 15 | /// 16 | /// The zlib-deflate-compressed ghost data 17 | /// 18 | [Property, Array] 19 | public byte[] CompressedData { get; set; } 20 | } 21 | 22 | [Chunk(0x0303F006)] 23 | public class GhostDataBoxedChunk 24 | : Chunk 25 | { 26 | [Property] 27 | public uint IsReplaying { get; set; } 28 | 29 | [Property, CustomParserMethod(nameof(ParseGhostData))] 30 | public GhostDataChunk GhostData { get; set; } 31 | 32 | public GhostDataChunk ParseGhostData(GameBoxReader reader) 33 | { 34 | return ParserFactory.GetChunkParser().Parse(reader, 0x0303F005); 35 | } 36 | } 37 | 38 | [CustomStruct] 39 | public class GhostData 40 | { 41 | [Property] 42 | public uint ClassId { get; set; } 43 | 44 | [Property] 45 | public bool SkipList2 { get; set; } 46 | 47 | [Property] 48 | public uint Unknown1 { get; set; } 49 | 50 | [Property] 51 | public uint SamplePeriod { get; set; } 52 | 53 | [Property] 54 | public uint Unknown2 { get; set; } 55 | 56 | [Property, Array] 57 | public byte[] SampleData { get; set; } 58 | 59 | [Property] 60 | public uint SampleCount { get; set; } 61 | 62 | [Property, Condition(nameof(SampleCount), ConditionOperator.GreaterThan, 0)] 63 | public uint FirstSampleOffset { get; set; } 64 | 65 | [Property, Condition(nameof(SampleCount), ConditionOperator.GreaterThan, 1)] 66 | public uint SizePerSample { get; set; } 67 | 68 | [EditorBrowsable(EditorBrowsableState.Never)] 69 | public uint SampleSizeCount => this.SampleCount - 1; 70 | 71 | [Property, Array(nameof(SampleSizeCount)), Condition(nameof(SizePerSample), ConditionOperator.Equal, uint.MaxValue)] 72 | public uint[] SampleSizes { get; set; } 73 | 74 | [Property, Array, Condition(nameof(SkipList2), ConditionOperator.Equal, false)] 75 | public int[] SampleTimes { get; set; } 76 | } 77 | 78 | [CustomStruct] 79 | public class GhostSampleRecord 80 | { 81 | [Property] 82 | public Vector3D Position { get; set; } 83 | 84 | [Property] 85 | public ushort AngleU { get; set; } 86 | 87 | public double Angle => this.AngleU * Math.PI / 0xFFFF; 88 | 89 | [Property] 90 | public short AxisHeadingS { get; set; } 91 | 92 | public double AxisHeading => this.AxisHeadingS * Math.PI / 0x8000; 93 | 94 | [Property] 95 | public short AxisPitchS { get; set; } 96 | 97 | public double AxisPitch => this.AxisPitchS * (Math.PI / 2) / 0x8000; 98 | 99 | [Property] 100 | public short SpeedS { get; set; } 101 | 102 | public double Speed => Math.Exp(this.SpeedS / 1000.0); 103 | 104 | [Property] 105 | public sbyte VelocityHeadingS { get; set; } 106 | 107 | public double VelocityHeading => this.VelocityHeadingS * Math.PI / 0x80; 108 | 109 | [Property] 110 | public sbyte VelocityPitchS { get; set; } 111 | 112 | public double VelocityPitch => this.VelocityPitchS * (Math.PI / 2) / 0x80; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostDisplayChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092017, Skippable = true)] 8 | public class GhostDisplayChunk 9 | : Chunk 10 | { 11 | [Property, Array] 12 | public FileReference[] SkinPackDescriptors { get; set; } 13 | 14 | [Property] 15 | public string GhostNickname { get; set; } 16 | 17 | [Property] 18 | public string GhostAvatarName { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostLightTrailColorChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092009, Skippable = true)] 8 | public class GhostLightTrailColorChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public Vector3D LightTrailColor { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostLoginChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0309200F)] 8 | public class GhostLoginChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public string Login { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostPlayerMobilIdChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(03092015)] 8 | public class GhostPlayerMobilIdChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.LookbackString)] 12 | public string PlayerMobilId { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostRaceTimeChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092005, Skippable = true)] 8 | public class GhostRaceTimeChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint RaceTimeU { get; set; } 13 | 14 | public TimeSpan RaceTime { get => TimeSpan.FromMilliseconds(this.RaceTimeU); } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostRespawnCountChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092008, Skippable = true)] 8 | public class GhostRespawnCountChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint RespawnCount { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostStuntScoreChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0309200A, Skippable = true)] 8 | public class GhostStuntScoreChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint StuntScore { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostUidChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0309200E)] 8 | public class GhostUidChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.LookbackString)] 12 | public string Uid { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostUnknown2Chunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0309200C)] 8 | public class GhostUnknown2Chunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Ignored { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostUnknown3Chunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092010)] 8 | public class GhostUnknown3Chunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.LookbackString)] 12 | public string Unknown { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostUnknown4Chunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092012)] 8 | public class GhostUnknown4Chunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Ignored { get; set; } 13 | 14 | [Property, Array(2)] 15 | public ulong[] Unknown { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostUnknown5Chunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092013, Skippable = true)] 8 | public class GhostUnknown5Chunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Unknown1 { get; set; } 13 | 14 | [Property] 15 | public uint Unknown2 { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostUnknown6Chunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092014, Skippable = true)] 8 | public class GhostUnknown6Chunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Unknown1 { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Ghost/GhostUnknown7Chunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03092018)] 8 | public class GhostUnknown7Chunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.LookbackString)] 12 | public string Unknown1 { get; set; } 13 | 14 | [Property(SpecialPropertyType.LookbackString)] 15 | public string Unknown2 { get; set; } 16 | 17 | [Property(SpecialPropertyType.LookbackString)] 18 | public string Unknown3 { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapAuthorChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x3043008)] 8 | public class MapAuthorChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Version { get; set; } 13 | 14 | [Property] 15 | public uint AuthorVersion { get; set; } 16 | 17 | [Property] 18 | public string Login { get; set; } 19 | 20 | [Property] 21 | public string Nick { get; set; } 22 | 23 | [Property] 24 | public string Zone { get; set; } 25 | 26 | [Property] 27 | public string ExtraInfo { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapCheckpointsChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ManiaPlanetSharp.GameBox.Parsing.ParserGeneration; 5 | 6 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 7 | { 8 | [Chunk(0x03043017, Skippable = true)] 9 | public class MapCheckpointsChunk 10 | : Chunk 11 | { 12 | [Property, Array] 13 | public Checkpoint[] Checkpoints { get; set; } 14 | } 15 | 16 | [CustomStruct] 17 | public class Checkpoint 18 | { 19 | [Property] 20 | public uint Value1 { get; set; } 21 | 22 | [Property] 23 | public uint Value2 { get; set; } 24 | 25 | [Property] 26 | public uint Value3 { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapCommonChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x3043003)] 8 | public class MapCommonChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public byte Version { get; set; } 13 | 14 | [Property(SpecialPropertyType.LookbackString)] 15 | public string Uid { get; set; } 16 | 17 | [Property(SpecialPropertyType.LookbackString)] 18 | public string Environment { get; set; } 19 | 20 | [Property(SpecialPropertyType.LookbackString)] 21 | public string Author { get; set; } 22 | 23 | [Property] 24 | public string Name { get; set; } 25 | 26 | [Property] 27 | [Obsolete("Raw Value, use GbxCommonClass.Kind instead", false)] 28 | public byte KindB { get; set; } 29 | 30 | public MapKind Kind { get => (MapKind)this.KindB; } 31 | 32 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 1)] 33 | public bool Locked { get; set; } 34 | 35 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 1)] 36 | [Obsolete("Legacy value, use GbxPasswordClass.Password instead", false)] 37 | public string Password { get; set; } 38 | 39 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 2)] 40 | public string DecorationTimeOfDay { get; set; } 41 | 42 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 2)] 43 | public string DecorationEnvironment { get; set; } 44 | 45 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 2)] 46 | public string DecorationEnvironmentAuthor { get; set; } 47 | 48 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 3)] 49 | public Vector2D Origin { get; set; } 50 | 51 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 4)] 52 | public Vector2D Target { get; set; } 53 | 54 | [Property, Array(16), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 5)] 55 | public byte[] Unused { get; set; } 56 | 57 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 6)] 58 | public string Type { get; set; } 59 | 60 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 6)] 61 | public string Style { get; set; } 62 | 63 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 6), Condition(nameof(Version), ConditionOperator.LessThanOrEqual, 8)] 64 | public bool UnusedFlag { get; set; } 65 | 66 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 8)] 67 | public ulong LightmapCacheUid { get; set; } 68 | 69 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 9)] 70 | public byte LightmapVersion { get; set; } 71 | 72 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 11)] 73 | public string TitleUid { get; set; } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapCoordinateChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03043025)] 8 | public class MapCoordinateChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public Vector2D Origin { get; set; } 13 | 14 | [Property] 15 | public Vector2D Target { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapCustomMusicChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03043024)] 8 | public class MapCustomMusicChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public FileReference CustomMusic { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapGlobalClipChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x03043026)] 8 | public class MapGlobalClipChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public Node GlobalClip { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapGmCamArchiveChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03043027)] 8 | public class MapGmCamArchiveChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public bool HasGmCamArchive { get; set; } 13 | 14 | [Property, Condition(nameof(HasGmCamArchive))] 15 | public byte Unknown1 { get; set; } 16 | 17 | [Property, Array(3), Condition(nameof(HasGmCamArchive))] 18 | public Vector3D[] Unknown2 { get; set; } 19 | 20 | [Property, Condition(nameof(HasGmCamArchive))] 21 | public Vector3D Unknown3 { get; set; } 22 | 23 | [Property, Condition(nameof(HasGmCamArchive))] 24 | public float Unknown4 { get; set; } 25 | 26 | [Property, Condition(nameof(HasGmCamArchive))] 27 | public float Unknown5 { get; set; } 28 | 29 | [Property, Condition(nameof(HasGmCamArchive))] 30 | public float Unknown6 { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapLapCountChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03043018, Skippable = true)] 8 | public class MapLapCountChunk 9 | { 10 | [Property] 11 | public bool Unused { get; set; } 12 | 13 | [Property] 14 | public uint LapCount { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapLightmapChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x0304303D, Skippable = true)] 8 | //The information here is outdated 9 | public class MapLightmapChunk 10 | : Chunk 11 | { 12 | [Property] 13 | public bool Unknown { get; set; } 14 | 15 | [Property] 16 | public uint Version { get; set; } 17 | 18 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 5)] 19 | public int FrameCount { get; set; } = 1; 20 | 21 | [Property, Array(nameof(FrameCount)), CustomParserMethod(nameof(ParseLightmapFrame))] 22 | public LightmapFrame[] Frames { get; set; } 23 | 24 | public LightmapFrame ParseLightmapFrame(GameBoxReader reader) 25 | { 26 | if (reader == null) 27 | { 28 | throw new ArgumentNullException(nameof(reader)); 29 | } 30 | 31 | LightmapFrame lightmapFrame = new LightmapFrame(); 32 | lightmapFrame.Image1 = reader.ReadRaw((int)reader.ReadUInt32()); 33 | if (this.Version >= 3) lightmapFrame.Image2 = reader.ReadRaw((int)reader.ReadUInt32()); 34 | if (this.Version >= 6) lightmapFrame.Image3 = reader.ReadRaw((int)reader.ReadUInt32()); 35 | return lightmapFrame; 36 | } 37 | } 38 | 39 | public class LightmapFrame 40 | { 41 | public byte[] Image1 { get; set; } 42 | public byte[] Image2 { get; set; } 43 | public byte[] Image3 { get; set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapMediaTrackerChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x03043021)] 8 | public class MapMediaTrackerChunk 9 | { 10 | [Property(SpecialPropertyType.NodeReference)] 11 | public Node IntroClip { get; set; } 12 | 13 | [Property(SpecialPropertyType.NodeReference)] 14 | public Node InGameClip { get; set; } 15 | 16 | [Property(SpecialPropertyType.NodeReference)] 17 | public Node EndRaceClip { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapModpackChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03043019, Skippable = true)] 8 | public class MapModpackChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public FileReference Modpack { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapPasswordChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03043029)] 8 | public class MapPasswordChunk 9 | : Chunk 10 | { 11 | [Property, Array(2)] 12 | public ulong[] Password { get; set; } 13 | 14 | [Property] 15 | public uint CRC { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapPasswordChunkOld.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03043014, Skippable = true)] 8 | public class MapPasswordChunkOld 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Unused { get; set; } 13 | 14 | [Property] 15 | public string Password { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapPlaymodeChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | #pragma warning disable CS0618 // Type or member is obsolete 6 | 7 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 8 | { 9 | [Chunk(0x0304301C, Skippable = true)] 10 | public class MapPlaymodeChunk 11 | : Chunk 12 | { 13 | [Property] 14 | [Obsolete("Raw Value, use GbxPlaymodeClass.Playmode instead", false)] 15 | public uint PlaymodeU { get; set; } 16 | public TrackType Playmode { get => (TrackType)this.PlaymodeU; } 17 | } 18 | 19 | public enum TrackType 20 | : uint 21 | { 22 | Race = 0, 23 | Platform = 1, 24 | Puzzle = 2, 25 | Crazy = 3, 26 | Shortcut = 4, 27 | Stunts = 5, 28 | Script = 6 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapThumbnailChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x3043007)] 8 | public class MapThumbnailChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Version { get; set; } 13 | 14 | [Property, CustomParserMethod(nameof(ReadThumbnailData)), Condition(nameof(Version), ConditionOperator.GreaterThan, 0)] 15 | public byte[] ThumbnailData { get; set; } 16 | 17 | [Property, CustomParserMethod(nameof(ReadComment)), Condition(nameof(Version), ConditionOperator.GreaterThan, 0)] 18 | public string Comment { get; set; } 19 | 20 | public byte[] ReadThumbnailData(GameBoxReader reader) 21 | { 22 | if (reader == null) 23 | { 24 | throw new ArgumentNullException(nameof(reader)); 25 | } 26 | 27 | uint thumbnailSize = reader.ReadUInt32(); 28 | reader.ReadString("".Length); 29 | var thumbnailData = reader.ReadRaw((int)thumbnailSize); 30 | reader.ReadString("".Length); 31 | return thumbnailData; 32 | } 33 | 34 | public string ReadComment(GameBoxReader reader) 35 | { 36 | if (reader == null) 37 | { 38 | throw new ArgumentNullException(nameof(reader)); 39 | } 40 | 41 | reader.ReadString("".Length); 42 | var comment = reader.ReadString(); 43 | reader.ReadString("".Length); 44 | return comment; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapTimeChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0305B004, Skippable = true)] 8 | public class MapTimeChunk 9 | : Chunk 10 | { 11 | [Property] 12 | [Obsolete("Raw Value, use GbxTimeClass.BronzeTime instead", false)] 13 | public uint BronzeTimeU { get; set; } 14 | 15 | public TimeSpan BronzeTime { get => TimeSpan.FromMilliseconds(this.BronzeTimeU); } 16 | 17 | [Property] 18 | [Obsolete("Raw Value, use GbxTimeClass.SilverTime instead", false)] 19 | public uint SilverTimeU { get; set; } 20 | 21 | public TimeSpan SilverTime { get => TimeSpan.FromMilliseconds(this.SilverTimeU); } 22 | 23 | [Property] 24 | [Obsolete("Raw Value, use GbxTimeClass.GoldTime instead", false)] 25 | public uint GoldTimeU { get; set; } 26 | 27 | public TimeSpan GoldTime { get => TimeSpan.FromMilliseconds(this.GoldTimeU); } 28 | 29 | [Property] 30 | [Obsolete("Raw Value, use GbxTimeClass.AuthorTime instead", false)] 31 | public uint AuthorTimeU { get; set; } 32 | 33 | public TimeSpan AuthorTime { get => TimeSpan.FromMilliseconds(this.AuthorTimeU); } 34 | 35 | [Property] 36 | public uint Ignored { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapTimelimitChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0305B008, Skippable = true)] 8 | public class MapTimelimitChunk 9 | : Chunk 10 | { 11 | [Property] 12 | [Obsolete("Raw Value, use GbxTimeLimitClass.TimeLimit instead", false)] 13 | public uint TimeLimitU { get; set; } 14 | 15 | public TimeSpan? TimeLimit { get => this.TimeLimitU != uint.MaxValue ? (TimeSpan?)TimeSpan.FromMilliseconds(this.TimeLimitU) : null; } 16 | 17 | [Property] 18 | [Obsolete("Raw Value, use MapTimelimitChunk.AuthorTime instead", false)] 19 | public uint AuthorTimeU { get; set; } 20 | 21 | public TimeSpan? AuthorTime { get => this.AuthorTimeU != uint.MaxValue ? (TimeSpan?)TimeSpan.FromMilliseconds(this.AuthorTimeU) : null; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapTimelimitTimeChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0305B00A, Skippable = true)] 8 | public class MapTimelimitTimeChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Unknown { get; set; } 13 | 14 | [Property] 15 | [Obsolete("Raw Value, use GbxTimeLimitTimeClass.BronzeTime instead", false)] 16 | public uint BronzeTimeU { get; set; } 17 | 18 | public TimeSpan BronzeTime { get => TimeSpan.FromMilliseconds(this.BronzeTimeU); } 19 | 20 | [Property] 21 | [Obsolete("Raw Value, use GbxTimeLimitTimeClass.SilverTime instead", false)] 22 | public uint SilverTimeU { get; set; } 23 | 24 | public TimeSpan SilverTime { get => TimeSpan.FromMilliseconds(this.SilverTimeU); } 25 | 26 | [Property] 27 | [Obsolete("Raw Value, use GbxTimeLimitTimeClass.GoldTime instead", false)] 28 | public uint GoldTimeU { get; set; } 29 | 30 | public TimeSpan GoldTime { get => TimeSpan.FromMilliseconds(this.GoldTimeU); } 31 | 32 | [Property] 33 | [Obsolete("Raw Value, use GbxTimeLimitTimeClass.AuthorTime instead", false)] 34 | public uint AuthorTimeU { get; set; } 35 | 36 | public TimeSpan AuthorTime { get => TimeSpan.FromMilliseconds(this.AuthorTimeU); } 37 | 38 | [Property] 39 | [Obsolete("Raw Value, use GbxTimeLimitTimeClass.TimeLimit instead", false)] 40 | public uint TimeLimitU { get; set; } 41 | 42 | public TimeSpan TimeLimit { get => TimeSpan.FromMilliseconds(this.TimeLimitU); } 43 | 44 | [Property] 45 | [Obsolete("Raw Value, use GbxTimeLimitTimeClass.AuthorScore instead", false)] 46 | public uint AuthorScoreU { get; set; } 47 | 48 | public TimeSpan AuthorScore { get => TimeSpan.FromMilliseconds(this.AuthorScoreU); } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapTipChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0305B001)] 8 | public class MapTipChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public string Tip1 { get; set; } 13 | 14 | [Property] 15 | public string Tip2 { get; set; } 16 | 17 | [Property] 18 | public string Tip3 { get; set; } 19 | 20 | [Property] 21 | public string Tip4 { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapVehicleChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x0304300D)] 8 | public class MapVehicleChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.LookbackString)] 12 | public string Name { get; set; } 13 | 14 | [Property(SpecialPropertyType.LookbackString)] 15 | public string Collection { get; set; } 16 | 17 | [Property(SpecialPropertyType.LookbackString)] 18 | public string Author { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Map/MapVersionChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x3043004)] 8 | public class MapVersionChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Version { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/MediaTracker/MediaTrackerTrianglesChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks.MediaTracker 6 | { 7 | [Chunk(0x03029001)] 8 | public class MediaTrackerTrianglesChunk001 9 | : Chunk 10 | { 11 | [Property, Array] 12 | public MediaTrackerTrianglesValue[] Values { get; set; } 13 | 14 | [Property] 15 | public uint TimestepCount { get; set; } 16 | 17 | [Property] 18 | public uint VerticeCount { get; set; } 19 | 20 | [Property, CustomParserMethod(nameof(MediaTrackerTrianglesChunk001.ParseVertices))] 21 | public Vector3D[][] VerticeLocations { get; set; } 22 | 23 | public Vector3D[][] ParseVertices(GameBoxReader reader) 24 | { 25 | List timesteps = new List(); 26 | for (int i = 0; i < this.TimestepCount; i++) 27 | { 28 | List buffer = new List(); 29 | for (int j = 0; j < this.VerticeCount; j++) 30 | { 31 | buffer.Add(reader.ReadVec3D()); 32 | } 33 | timesteps.Add(buffer.ToArray()); 34 | } 35 | return timesteps.ToArray(); 36 | } 37 | 38 | [Property, Array] 39 | public MediaTrackerTrianglesColor[] VerticeColors { get; set; } 40 | 41 | [Property, Array] 42 | public MediaTrackerTrianglesTriangleVerticeIndices[] Triangles { get; set; } 43 | 44 | [Property] 45 | public uint Unknown1 { get; set; } 46 | 47 | [Property] 48 | public uint Unknown2 { get; set; } 49 | 50 | [Property] 51 | public uint Unknown3 { get; set; } 52 | 53 | [Property] 54 | public float Unknown4 { get; set; } 55 | 56 | [Property] 57 | public uint Unknown5 { get; set; } 58 | 59 | [Property] 60 | public uint Unknown6 { get; set; } 61 | 62 | [Property] 63 | public uint Unknown7 { get; set; } 64 | } 65 | 66 | [CustomStruct] 67 | public class MediaTrackerTrianglesValue 68 | { 69 | [Property] 70 | public float Timestamp { get; set; } 71 | } 72 | 73 | [CustomStruct] 74 | public class MediaTrackerTrianglesColor 75 | { 76 | [Property] 77 | public float R { get; set; } 78 | 79 | [Property] 80 | public float G { get; set; } 81 | 82 | [Property] 83 | public float B { get; set; } 84 | 85 | [Property] 86 | public float A { get; set; } 87 | } 88 | 89 | [CustomStruct] 90 | public class MediaTrackerTrianglesTriangleVerticeIndices 91 | { 92 | [Property, Array(3)] 93 | public int[] VerticeIndices { get; set; } 94 | } 95 | 96 | [Chunk(0x03029002, Skippable = true)] 97 | public class MediaTrackerTrianglesChunk002 98 | : Chunk 99 | { 100 | [Property] 101 | public int Unknown { get; set; } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectAnchorChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E002017)] 8 | public class ObjectAnchorChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public int Version { get; set; } 13 | 14 | [Property] 15 | public bool IsFreelyAnchorable { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectAudioEnvironmentChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x2E002013)] 8 | public class ObjectAudioEnvironmentChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.NodeReference)] 12 | public Node InCarAudioEnvironment { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectBannerProfileChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E002010)] 8 | public class ObjectBannerProfileChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public FileReference BannerProfile { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectBaseAttributesChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x2E002014)] 8 | public class ObjectBaseAttributesChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.NodeReference)] 12 | public Node BaseAttributes { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectCameraIndexChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E002006)] 8 | public class ObjectCameraIndexChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint DefaultCameraIndex { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectCamerasChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x2E002009)] 8 | public class ObjectCamerasChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Version { get; set; } 13 | 14 | [Property(SpecialPropertyType.NodeReference), Array] 15 | public Node[] Cameras { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectDecoratorSolidChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x2E00200A)] 8 | public class ObjectDecoratorSolidChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public Node DecoratorSolid { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectDefaultSkinChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x2E002016)] 8 | public class ObjectDefaultSkinChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public FileReference DefaultSkin { get; set; } //Might be node 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectGroundPointChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E002012)] 8 | public class ObjectGroundPointChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public Vector3D GroundPoint { get; set; } 13 | 14 | [Property] 15 | public float PainterGroundMargin { get; set; } 16 | 17 | [Property] 18 | public float OrbitalCenterHeightFromGround { get; set; } 19 | 20 | [Property] 21 | public float OrbitalRadiusBase { get; set; } 22 | 23 | [Property] 24 | public float OrbitalPreviewAngle { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectItemTypeChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E002000)] 8 | public class ObjectItemTypeChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint ItemTypeU { get; set; } 13 | 14 | public ObjectType ItemType => (ObjectType)this.ItemTypeU; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectMaterialChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x2E00200B)] 8 | public class ObjectMaterialChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.NodeReference)] 12 | public Node StemMaterial { get; set; } 13 | 14 | [Property(SpecialPropertyType.NodeReference)] 15 | public Node StemBumpMaterial { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectNadeoSkinFileChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x2E002008)] 8 | public class ObjectNadeoSkinFileChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.NodeReference), Array] 12 | public Node[] Files { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectRaceInterfaceChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x2E00200C)] 8 | public class ObjectRaceInterfaceChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.NodeReference)] 12 | public Node RaceInterface { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectTypeChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E002015)] 8 | public class ObjectTypeChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint ObjectTypeU { get; set; } 13 | public ObjectType ObjectType => (ObjectType)this.ObjectTypeU; 14 | } 15 | 16 | public enum ObjectType 17 | : uint 18 | { 19 | Undefined = 0, 20 | Ornament = 1, 21 | PickUp = 2, 22 | Character = 3, 23 | Vehicle = 4, 24 | Spot = 5, 25 | Cannon = 6, 26 | Group = 7, 27 | Decal = 8, 28 | Turret = 9, 29 | Wagon = 10, 30 | Block = 11, 31 | EntitySpawner = 12 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectUnknownChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E002001)] 8 | public class ObjectUnknownChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Unknown { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Object/ObjectUsabilityChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x2E002018)] 8 | public class ObjectUsabilityChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public int Version { get; set; } 13 | 14 | [Property] 15 | public bool IsUsable { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Other/GameSkinChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x090F4000)] 8 | public class GameSkinChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public byte Version { get; set; } 13 | 14 | [Property] 15 | public string DirectoryName { get; set; } 16 | 17 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 1)] 18 | public string TextureName { get; set; } 19 | 20 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 1)] 21 | public string SceneId { get; set; } 22 | 23 | [Property, CustomParserMethod(nameof(ParseSkinFiles))] 24 | public SkinFile[] SkinFiles { get; set; } 25 | 26 | public SkinFile[] ParseSkinFiles(GameBoxReader reader) 27 | { 28 | if (reader == null) 29 | { 30 | throw new ArgumentNullException(nameof(reader)); 31 | } 32 | 33 | SkinFile[] skinFiles = new SkinFile[reader.ReadByte()]; 34 | for (int i = 0; i < skinFiles.Length; i++) 35 | { 36 | skinFiles[i] = new SkinFile() 37 | { 38 | ClassId = reader.ReadUInt32(), 39 | Name = reader.ReadString(), 40 | File = reader.ReadString() 41 | }; 42 | if (this.Version >= 2) 43 | { 44 | skinFiles[i].NeedsMipMap = reader.ReadBool(); 45 | } 46 | } 47 | 48 | return skinFiles; 49 | } 50 | 51 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 4)] 52 | public string AlternateDirectoryName { get; set; } 53 | 54 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 5)] 55 | public bool UseDefaultSkin { get; set; } 56 | } 57 | 58 | [CustomStruct] 59 | public class SkinFile 60 | { 61 | public uint ClassId { get; set; } 62 | 63 | public string Name { get; set; } 64 | 65 | public string File { get; set; } 66 | 67 | public bool NeedsMipMap { get; set; } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Other/PackDescriptionChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ManiaPlanetSharp.GameBox.Parsing.ParserGeneration; 5 | 6 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 7 | { 8 | //[Chunk(0x03059000), Chunk(0x03059001), Chunk(0x03059002)] 9 | public class PackDescriptionChunk 10 | : Chunk 11 | { 12 | public string Text { get; set; } 13 | 14 | [Property, Condition(nameof(PackDescriptionChunk.ChunkId), ConditionOperator.Equal, 0)] 15 | public string Ignored { get; set; } 16 | 17 | [Property, Condition(nameof(PackDescriptionChunk.ChunkId), ConditionOperator.GreaterThanOrEqual, 1)] 18 | public FileReference Pack { get; set; } 19 | 20 | [Property, Condition(nameof(PackDescriptionChunk.ChunkId), ConditionOperator.GreaterThanOrEqual, 2)] 21 | public FileReference ParentPack { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Other/PhysicalModelChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks.Other 6 | { 7 | //[Chunk(0x2E006000)] 8 | public class PhysicalModelChunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.NodeReference)] 12 | public Node Unknown1 { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Other/WaypointSpecialPropertyChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ManiaPlanetSharp.GameBox.Parsing.ParserGeneration; 5 | 6 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 7 | { 8 | [Chunk(0x2E009000)] 9 | public class WaypointSpecialPropertyChunk 10 | : Chunk 11 | { 12 | [Property] 13 | public uint Version { get; set; } 14 | 15 | [Property, Condition(nameof(WaypointSpecialPropertyChunk.Version), ConditionOperator.Equal, 1)] 16 | public uint Spawn { get; set; } 17 | 18 | [Property, Condition(nameof(WaypointSpecialPropertyChunk.Version), ConditionOperator.GreaterThan, 1)] 19 | public string Tag { get; set; } 20 | 21 | [Property] 22 | public uint Order { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Replay/ReplayGhostsChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03093014)] 8 | public class ReplayGhostsChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Ignored1 { get; set; } 13 | 14 | [Property(SpecialPropertyType.NodeReference), Array] 15 | public Node[] Ghosts { get; set; } 16 | 17 | [Property] 18 | public uint Ignored2 { get; set; } 19 | 20 | [Property, Array] 21 | public ulong[] Extras { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Replay/ReplayMainChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 7 | { 8 | [Chunk(0x03093002)] 9 | public class ReplayMainChunk 10 | : Chunk 11 | { 12 | [Property, CustomParserMethod(nameof(ParseContent))] 13 | public ReplayMainChunkContent Content { get; set; } 14 | 15 | public ReplayMainChunkContent ParseContent(GameBoxReader reader) 16 | { 17 | if (reader == null) 18 | { 19 | throw new ArgumentNullException(nameof(reader)); 20 | } 21 | 22 | if (reader.BodyMode) 23 | { 24 | return ParserFactory.GetCustomStructParser().Parse(reader); 25 | } 26 | else 27 | { 28 | return ParserFactory.GetCustomStructParser().Parse(reader); 29 | } 30 | } 31 | } 32 | 33 | public class ReplayMainChunkContent 34 | { } 35 | 36 | [CustomStruct] 37 | public class ReplayMainChunkHeaderContent 38 | : ReplayMainChunkContent 39 | { 40 | [Property] 41 | public uint Version { get; set; } 42 | 43 | [Property] 44 | public uint AuthorVersion { get; set; } 45 | 46 | [Property] 47 | public string Login { get; set; } 48 | 49 | [Property] 50 | public string Nickname { get; set; } 51 | 52 | [Property] 53 | public string Zone { get; set; } 54 | 55 | [Property] 56 | public string ExtraInfo { get; set; } 57 | } 58 | 59 | [CustomStruct] 60 | public class ReplayMainChunkBodyContent 61 | : ReplayMainChunkContent 62 | { 63 | [Property, Array] 64 | public byte[] MapData { get; set; } 65 | 66 | [Property, CustomParserMethod(nameof(ParseMap))] 67 | public GameBoxFile MapFile { get; set; } 68 | 69 | public GameBoxFile ParseMap(GameBoxReader reader) 70 | { 71 | if (this.MapData == null) 72 | { 73 | throw new NullReferenceException("No map data available."); 74 | } 75 | if (this.MapData.Length == 0) 76 | { 77 | return new GameBoxFile(); 78 | } 79 | 80 | using (MemoryStream stream = new MemoryStream(this.MapData)) 81 | { 82 | return GameBoxFile.Parse(stream); 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Replay/ReplayUnknown2Chunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | //[Chunk(0x03093015)] 8 | public class ReplayUnknown2Chunk 9 | : Chunk 10 | { 11 | [Property(SpecialPropertyType.NodeReference)] 12 | public Node Node { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Replay/ReplayUnknownChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03093007, Skippable = true)] 8 | public class ReplayUnknownChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Unknown { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Replay/ReplayVersionChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks 6 | { 7 | [Chunk(0x03093000)] 8 | public class ReplayVersionChunk 9 | : Chunk 10 | { 11 | [Property] 12 | public uint Version { get; set; } 13 | 14 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 2)] 15 | public string TrackUid { get; set; } 16 | 17 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 2)] 18 | public string TrackEnvironment { get; set; } 19 | 20 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 2)] 21 | public string TrackAuthor { get; set; } 22 | 23 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 2)] 24 | public uint TimeU { get; set; } 25 | public TimeSpan Time => TimeSpan.FromMilliseconds(this.TimeU); 26 | 27 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 2)] 28 | public string Nickname { get; set; } 29 | 30 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 6)] 31 | public string Login { get; set; } 32 | 33 | [Property, Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 8)] 34 | public byte Unused { get; set; } 35 | 36 | [Property(SpecialPropertyType.LookbackString), Condition(nameof(Version), ConditionOperator.GreaterThanOrEqual, 8)] 37 | public string TitleUid { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/TMUnlimiter/LegacyParameterSetChunk.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using ManiaPlanetSharp.TMUnlimiter; 3 | using VersionBackendUnlimiter13 = ManiaPlanetSharp.TMUnlimiter.Version13.VersionBackend; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks.TMUnlimiter 6 | { 7 | [Chunk(0x3f_003_00fu, skippable: true)] 8 | public class LegacyParameterSetChunk : Chunk 9 | { 10 | [Property, CustomParserMethod(nameof(Archive))] 11 | public ParameterSet ParameterSet { get; set; } 12 | 13 | #pragma warning disable CA1062 // Validate arguments of public methods -- Reader is always guaranteed to be non-null. 14 | public ParameterSet Archive( GameBoxReader reader ) 15 | { 16 | reader.Stream.Seek( -4, System.IO.SeekOrigin.Current ); 17 | // Chunk size is an unsigned integer, but MemoryStream works on integers instead... 18 | int chunkSize = reader.ReadInt32(); 19 | 20 | // Decrypt weakly encrypted TMUnlimiter 1.3 chunk 21 | byte[] cryptedChunkData = VersionBackendUnlimiter13.DecryptChunkData( reader.ReadRaw( chunkSize ) ); 22 | 23 | using ( GameBoxReader innerReader = new GameBoxReader( new MemoryStream( cryptedChunkData ) ) ) 24 | { 25 | ParameterSet parameterSet = new ParameterSet(); 26 | uint parameterCount = innerReader.ReadUInt32(); 27 | 28 | for ( uint parameterIndex = 0; parameterIndex < parameterCount; parameterIndex++ ) 29 | { 30 | ParameterFunction parameterFunction = VersionBackendUnlimiter13.GetParameterFunction( innerReader.ReadByte(), innerReader.ReadByte() ); 31 | 32 | if ( parameterFunction == null ) 33 | { 34 | continue; 35 | } 36 | 37 | switch ( parameterFunction.ValueType ) 38 | { 39 | case ParameterValueType.Number: 40 | { 41 | parameterSet.Parameters.Add( new ParameterNumber( parameterFunction, innerReader.ReadFloat() ) ); 42 | break; 43 | } 44 | case ParameterValueType.String: 45 | { 46 | parameterSet.Parameters.Add( new ParameterString( parameterFunction, innerReader.ReadString( innerReader.ReadByte() ) ) ); 47 | break; 48 | } 49 | default: 50 | { 51 | parameterSet.Parameters.Add( new Parameter( parameterFunction ) ); 52 | break; 53 | } 54 | } 55 | } 56 | 57 | return parameterSet.Parameters.Count > 0 ? parameterSet : null; 58 | } 59 | } 60 | #pragma warning restore CA1062 // Validate arguments of public methods -- Reader is always guaranteed to be non-null. 61 | } 62 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/Chunks/TMUnlimiter/LegacyScriptChunk.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using ManiaPlanetSharp.TMUnlimiter; 3 | using VersionBackendUnlimiter13 = ManiaPlanetSharp.TMUnlimiter.Version13.VersionBackend; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing.Chunks.TMUnlimiter 6 | { 7 | [Chunk(0x3f_004_00fu, skippable: true)] 8 | public class LegacyScriptChunk : Chunk 9 | { 10 | [Property, CustomParserMethod(nameof(Archive))] 11 | public LegacyScript LegacyScript { get; set; } 12 | 13 | #pragma warning disable CA1062 // Validate arguments of public methods -- Reader is always guaranteed to be non-null. 14 | public LegacyScript Archive( GameBoxReader reader ) 15 | { 16 | reader.Stream.Seek( -4, System.IO.SeekOrigin.Current ); 17 | // Chunk size is an unsigned integer, but MemoryStream works on integers instead... 18 | int chunkSize = reader.ReadInt32(); 19 | 20 | // Decrypt weakly encrypted TMUnlimiter 1.3 chunk 21 | byte[] cryptedChunkData = VersionBackendUnlimiter13.DecryptChunkData( reader.ReadRaw( chunkSize ) ); 22 | 23 | using ( GameBoxReader innerReader = new GameBoxReader( new MemoryStream( cryptedChunkData ) ) ) 24 | { 25 | LegacyScriptExecutionType executionType; 26 | 27 | // Match legacy script execution type 28 | switch ( innerReader.ReadByte() ) 29 | { 30 | case 1: 31 | { 32 | executionType = LegacyScriptExecutionType.TriggerAlways; 33 | break; 34 | } 35 | case 2: 36 | { 37 | executionType = LegacyScriptExecutionType.TriggerInside; 38 | break; 39 | } 40 | default: 41 | { 42 | executionType = LegacyScriptExecutionType.TriggerOnce; 43 | break; 44 | } 45 | } 46 | 47 | // Chunk size is an unsigned integer, but MemoryStream works on integers instead... 48 | return new LegacyScript( innerReader.ReadRaw( innerReader.ReadInt32() ), executionType ); 49 | } 50 | } 51 | #pragma warning restore CA1062 // Validate arguments of public methods -- Reader is always guaranteed to be non-null. 52 | } 53 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/GlobalParserSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing 6 | { 7 | /// 8 | /// Manages global settings for the GameBox parser 9 | /// 10 | public static class GlobalParserSettings 11 | { 12 | /// 13 | /// The maximum size in bytes for which the body of a GameBox file will be analyzed. If the body size of a GameBox file exceeds this limit, an exception will be thrown. 14 | /// 15 | public static uint MaximumUncompressedGameBoxBodySize { get; set; } = 100000000; //100MB 16 | 17 | private static bool usePrecompiledParsers = true; 18 | /// 19 | /// Specifies whether precompiled parsers from the ManiaPlanetSharp.GameBox.AutoGenerated assembly should be used, should they be present. This is primarily for development and testing purposes, as the proper way to disable the use of precompiled parsers is to just not include the additional assembly and not change any settings here. 20 | /// 21 | public static bool UsePrecompiledParsersIfPresent 22 | { 23 | get 24 | { 25 | return usePrecompiledParsers; 26 | } 27 | set 28 | { 29 | if (value != UsePrecompiledParsersIfPresent) 30 | { 31 | usePrecompiledParsers = value; 32 | if (UsePrecompiledParsersIfPresent) 33 | { 34 | ParserFactory.InitializePrecompiledParsers(); 35 | } 36 | else 37 | { 38 | ParserFactory.ClearParsers(); 39 | } 40 | } 41 | } 42 | } 43 | 44 | private static bool useDynamicallyCompiledChunkParsers = true; 45 | /// 46 | /// Specifies whether dynamically generated and compiled parsers should be used if no precompiled parser is available (or they are disabled). 47 | /// 48 | public static bool UseDynamicallyCompiledChunkParsers 49 | { 50 | get 51 | { 52 | return useDynamicallyCompiledChunkParsers; 53 | } 54 | set 55 | { 56 | if (value != UseDynamicallyCompiledChunkParsers) 57 | { 58 | useDynamicallyCompiledChunkParsers = value; 59 | if (!UseDynamicallyCompiledChunkParsers) 60 | { 61 | ParserFactory.ClearParsers(); 62 | ParserFactory.InitializePrecompiledParsers(); 63 | } 64 | else 65 | { 66 | ParserFactory.ScanForParseableChunks(); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParserGeneration/Attributes/ArrayAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing 6 | { 7 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] 8 | public class ArrayAttribute 9 | : Attribute 10 | { 11 | public ArrayAttribute() 12 | { 13 | this.LengthSource = new AutomaticArrayLengthSource(); 14 | } 15 | 16 | public ArrayAttribute(int length) 17 | { 18 | this.LengthSource = new FixedArrayLengthSource(length); 19 | } 20 | 21 | public ArrayAttribute(string lengthProperty) 22 | { 23 | this.LengthSource = new PropertyArrayLengthSource(lengthProperty); 24 | } 25 | 26 | public ArrayLengthSource LengthSource { get; private set; } 27 | } 28 | 29 | public abstract class ArrayLengthSource 30 | { } 31 | 32 | public class AutomaticArrayLengthSource 33 | : ArrayLengthSource 34 | { } 35 | 36 | public class FixedArrayLengthSource 37 | : ArrayLengthSource 38 | { 39 | public FixedArrayLengthSource(int length) 40 | { 41 | if (length < 0) throw new ArgumentOutOfRangeException(nameof(length)); 42 | this.Length = length; 43 | } 44 | 45 | public int Length { get; private set; } 46 | } 47 | 48 | public class PropertyArrayLengthSource 49 | : ArrayLengthSource 50 | { 51 | public PropertyArrayLengthSource(string dependentProperty) 52 | { 53 | this.DependentProperty = dependentProperty; 54 | } 55 | 56 | public string DependentProperty { get; private set; } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParserGeneration/Attributes/ChunkAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing 6 | { 7 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] 8 | public class ChunkAttribute 9 | : Attribute 10 | { 11 | public ChunkAttribute(uint id) 12 | { 13 | this.Id = id; 14 | } 15 | public ChunkAttribute(uint id, bool skippable) 16 | : this(id) 17 | { 18 | this.Skippable = skippable; 19 | } 20 | 21 | public uint Id { get; private set; } 22 | 23 | public bool Skippable { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParserGeneration/Attributes/ConditionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing 6 | { 7 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)] 8 | public class ConditionAttribute 9 | : Attribute 10 | { 11 | protected ConditionAttribute() 12 | { } 13 | 14 | public ConditionAttribute(string dependentProperty, ConditionOperator conditionOperator, object referenceValue) 15 | : this() 16 | { 17 | this.Condition = new ValueCondition(dependentProperty, conditionOperator, referenceValue); 18 | } 19 | 20 | public ConditionAttribute(string dependentProperty, bool referenceValue) 21 | : this() 22 | { 23 | this.Condition = new BinaryCondition(dependentProperty, referenceValue); 24 | } 25 | 26 | public ConditionAttribute(string dependentProperty) 27 | : this() 28 | { 29 | this.Condition = new BinaryCondition(dependentProperty); 30 | } 31 | 32 | 33 | public Condition Condition { get; private set; } 34 | } 35 | 36 | public abstract class Condition 37 | { } 38 | 39 | public abstract class PropertyDependentCondition 40 | : Condition 41 | { 42 | protected PropertyDependentCondition(string dependentProperty) 43 | { 44 | this.DependentProperty = dependentProperty; 45 | } 46 | 47 | public string DependentProperty { get; private set; } 48 | } 49 | 50 | public enum ConditionOperator 51 | { 52 | LessThan, 53 | LessThanOrEqual, 54 | Equal, 55 | GreaterThanOrEqual, 56 | GreaterThan, 57 | NotEqual, 58 | HasFlag, 59 | DoesNotHaveFlag 60 | } 61 | 62 | public class ValueCondition 63 | : PropertyDependentCondition 64 | { 65 | public ValueCondition(string dependentProperty, ConditionOperator conditionOperator, object referenceValue) 66 | : base(dependentProperty) 67 | { 68 | this.Comparison = conditionOperator; 69 | this.ReferenceValue = referenceValue; 70 | } 71 | 72 | public ConditionOperator Comparison { get; private set; } 73 | public object ReferenceValue { get; private set; } 74 | } 75 | 76 | public class BinaryCondition 77 | : PropertyDependentCondition 78 | { 79 | public BinaryCondition(string dependentProperty, bool referenceValue) 80 | : base(dependentProperty) 81 | { 82 | this.ReferenceValue = referenceValue; 83 | } 84 | 85 | public BinaryCondition(string dependentProperty) 86 | : this(dependentProperty, true) 87 | { } 88 | 89 | public bool ReferenceValue { get; private set; } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParserGeneration/Attributes/CustomParserMethodAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing 6 | { 7 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] 8 | public class CustomParserMethodAttribute 9 | : Attribute 10 | { 11 | public CustomParserMethodAttribute(string parserMethod) 12 | { 13 | this.ParserMethod = parserMethod; 14 | } 15 | 16 | public string ParserMethod { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParserGeneration/Attributes/CustomStructAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing 6 | { 7 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 8 | public class CustomStructAttribute 9 | : Attribute 10 | { } 11 | } 12 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParserGeneration/Attributes/PropertyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using System.Text; 5 | 6 | namespace ManiaPlanetSharp.GameBox.Parsing 7 | { 8 | public enum SpecialPropertyType 9 | { 10 | LookbackString, 11 | NodeReference, 12 | LongString, 13 | //CustomStruct 14 | } 15 | 16 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] 17 | public class PropertyAttribute 18 | : Attribute 19 | { 20 | public PropertyAttribute([CallerLineNumber]int line = 0) 21 | { 22 | this.Line = line; 23 | } 24 | 25 | public PropertyAttribute(SpecialPropertyType specialType, [CallerLineNumber]int line = 0) 26 | : this(line) 27 | { 28 | this.SpecialType = specialType; 29 | } 30 | 31 | public SpecialPropertyType? SpecialType { get; private set; } 32 | 33 | protected internal int Line { get; private set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParserGeneration/Field.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | 7 | namespace ManiaPlanetSharp.GameBox.Parsing.ParserGeneration 8 | { 9 | public static class Fields 10 | { 11 | public static IEnumerable GetFields() 12 | { 13 | foreach (PropertyInfo property in typeof(T).GetProperties()) 14 | { 15 | PropertyAttribute propertyAttribute = property.GetCustomAttribute(); 16 | if (propertyAttribute != null) 17 | { 18 | yield return new Field() 19 | { 20 | Property = property, 21 | Index = propertyAttribute.Line, 22 | SpecialPropertyType = propertyAttribute.SpecialType, 23 | ArrayLengthSource = property.GetCustomAttribute()?.LengthSource, 24 | Conditions = property.GetCustomAttributes().Select(conditionAttribute => conditionAttribute.Condition).ToList(), 25 | CustomParserMethod = property.GetCustomAttribute()?.ParserMethod 26 | }; 27 | } 28 | } 29 | } 30 | } 31 | 32 | public class Field 33 | { 34 | public PropertyInfo Property { get; set; } 35 | public int Index { get; set; } 36 | 37 | public bool HasSpecialPropertyType => this.SpecialPropertyType != null; 38 | public SpecialPropertyType? SpecialPropertyType { get; set; } 39 | public bool HasConditions => this.Conditions != null ? this.Conditions.Any() : false; 40 | public List Conditions { get; set; } 41 | public bool IsArray => this.ArrayLengthSource != null; 42 | public ArrayLengthSource ArrayLengthSource { get; set; } 43 | public bool HasCustomParser => this.CustomParserMethod != null; 44 | public string CustomParserMethod { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParserGeneration/ParserGeneratorException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace ManiaPlanetSharp.GameBox.Parsing.ParserGeneration 5 | { 6 | [Serializable] 7 | public class ParserGeneratorException 8 | : Exception 9 | { 10 | public ParserGeneratorException() 11 | { } 12 | 13 | public ParserGeneratorException(string message) 14 | : base(message) 15 | { } 16 | 17 | public ParserGeneratorException(string message, Exception innerException) 18 | : base(message, innerException) 19 | { } 20 | 21 | protected ParserGeneratorException(SerializationInfo info, StreamingContext context) 22 | : base(info, context) 23 | { } 24 | } 25 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Parsing/ParsingErrorLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox.Parsing 6 | { 7 | public static class ParsingErrorLogger 8 | { 9 | public static event EventHandler ParsingErrorOccured; 10 | 11 | internal static void OnParsingErrorOccured(object sender, ParsingErrorEventArgs args) 12 | { 13 | ParsingErrorOccured?.Invoke(sender, args); 14 | } 15 | } 16 | 17 | public class ParsingErrorEventArgs 18 | : EventArgs 19 | { 20 | public ParsingErrorEventArgs(uint chunkId, string message) 21 | { 22 | this.ChunkId = chunkId; 23 | this.Message = message; 24 | } 25 | 26 | public uint ChunkId { get; private set; } 27 | public string Message { get; private set; } 28 | 29 | public override string ToString() => $"Chunk 0x{this.ChunkId:X8}.\n\n{this.Message}"; 30 | } 31 | 32 | public class BodyParsingErrorEventArgs 33 | : ParsingErrorEventArgs 34 | { 35 | public BodyParsingErrorEventArgs(uint chunkId, long position, string message) 36 | : base(chunkId, message) 37 | { 38 | this.Position = position; 39 | } 40 | 41 | public long Position { get; private set; } 42 | 43 | public override string ToString() => $"Chunk 0x{this.ChunkId:X8} at {this.Position}.\n\n{this.Message}"; 44 | } 45 | 46 | public class NodeInternalParsingErrorEventArgs 47 | : ParsingErrorEventArgs 48 | { 49 | public NodeInternalParsingErrorEventArgs(Node node, uint chunkId, string message) 50 | : base(chunkId, message) 51 | { 52 | this.ClassId = node?.ClassId ?? 0; 53 | } 54 | 55 | public uint ClassId { get; private set; } 56 | 57 | public override string ToString() => $"Chunk 0x{this.ChunkId:X8} in Node 0x{this.ClassId:X8}.\n\n{this.Message}"; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Types/FileFormat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox 6 | { 7 | public enum FileFormat 8 | { 9 | Binary, 10 | Text 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Types/FileReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox 6 | { 7 | public class FileReference 8 | { 9 | public byte Version { get; set; } 10 | 11 | public byte[] Checksum { get; set; } 12 | 13 | public string FilePath { get; set; } 14 | 15 | public bool IsRelativePath => this.Version < 2; 16 | 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1056:Uri properties should not be strings", Justification = "")] 18 | public string LocatorUrl { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Types/GameCtnBlockSkin.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.GameBox.Types 2 | { 3 | public class GameCtnBlockSkin 4 | { 5 | public string Text { get; set; } 6 | public FileReference PackDesc { get; set; } 7 | public FileReference ParentPackDesc { get; set; } 8 | public FileReference ForegroundPackDesc { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Types/Size2D.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox 6 | { 7 | public struct Size2D 8 | : IEquatable 9 | { 10 | public Size2D(int x, int y) 11 | { 12 | this.X = x; 13 | this.Y = y; 14 | } 15 | 16 | public int X { get; set; } 17 | public int Y { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return $"Size2D {{ X = {this.X}, Y = {this.Y} }}"; 22 | } 23 | 24 | public override bool Equals(object obj) 25 | { 26 | return obj is Size2D s && this.Equals(s); 27 | } 28 | 29 | public bool Equals(Size2D other) 30 | { 31 | return this.X == other.X && this.Y == other.Y; 32 | } 33 | 34 | public override int GetHashCode() 35 | { 36 | return this.X.GetHashCode() ^ this.Y.GetHashCode(); 37 | } 38 | 39 | public static bool operator ==(Size2D left, Size2D right) 40 | { 41 | return left.Equals(right); 42 | } 43 | 44 | public static bool operator !=(Size2D left, Size2D right) 45 | { 46 | return !(left == right); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Types/Size3D.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox 6 | { 7 | public struct Size3D 8 | : IEquatable 9 | { 10 | public Size3D(int x, int y, int z) 11 | { 12 | this.X = x; 13 | this.Y = y; 14 | this.Z = z; 15 | } 16 | 17 | public int X { get; set; } 18 | public int Y { get; set; } 19 | public int Z { get; set; } 20 | 21 | public override string ToString() 22 | { 23 | return $"Size3D {{ X = {this.X}, Y = {this.Y}, Z = {this.Z} }}"; 24 | } 25 | 26 | public override bool Equals(object obj) 27 | { 28 | return obj is Size3D s && this.Equals(s); 29 | } 30 | 31 | public bool Equals(Size3D other) 32 | { 33 | return this.X == other.X && this.Y == other.Y && this.Z == other.Z; 34 | } 35 | 36 | public override int GetHashCode() 37 | { 38 | return this.X.GetHashCode() ^ this.Y.GetHashCode() ^ this.Z.GetHashCode(); 39 | } 40 | 41 | public static bool operator ==(Size3D left, Size3D right) 42 | { 43 | return left.Equals(right); 44 | } 45 | 46 | public static bool operator !=(Size3D left, Size3D right) 47 | { 48 | return !(left == right); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Types/Vector2D.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox 6 | { 7 | public struct Vector2D 8 | : IEquatable 9 | { 10 | public Vector2D(float x, float y) 11 | { 12 | this.X = x; 13 | this.Y = y; 14 | } 15 | 16 | public float X { get; set; } 17 | public float Y { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return $"Vector2D {{ X = {this.X}, Y = {this.Y} }}"; 22 | } 23 | 24 | public override bool Equals(object obj) 25 | { 26 | return obj is Vector2D v && this.Equals(v); 27 | } 28 | 29 | public bool Equals(Vector2D other) 30 | { 31 | return this.X == other.X && this.Y == other.Y; 32 | } 33 | 34 | public override int GetHashCode() 35 | { 36 | return this.X.GetHashCode() ^ this.Y.GetHashCode(); 37 | } 38 | 39 | public static bool operator ==(Vector2D left, Vector2D right) 40 | { 41 | return left.Equals(right); 42 | } 43 | 44 | public static bool operator !=(Vector2D left, Vector2D right) 45 | { 46 | return !(left == right); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GameBox/Types/Vector3D.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.GameBox 6 | { 7 | public struct Vector3D 8 | : IEquatable 9 | { 10 | public Vector3D(float x, float y, float z) 11 | { 12 | this.X = x; 13 | this.Y = y; 14 | this.Z = z; 15 | } 16 | 17 | public float X { get; set; } 18 | public float Y { get; set; } 19 | public float Z { get; set; } 20 | 21 | public override string ToString() 22 | { 23 | return $"Vector3D {{ X = {this.X}, Y = {this.Y}, Z = {this.Z} }}"; 24 | } 25 | 26 | public override bool Equals(object obj) 27 | { 28 | return obj is Vector3D v && this.Equals(v); 29 | } 30 | 31 | public bool Equals(Vector3D other) 32 | { 33 | return this.X == other.X && this.Y == other.Y && this.Z == other.Z; 34 | } 35 | 36 | public override int GetHashCode() 37 | { 38 | return this.X.GetHashCode() ^ this.Y.GetHashCode() ^ this.Z.GetHashCode(); 39 | } 40 | 41 | public static bool operator ==(Vector3D left, Vector3D right) 42 | { 43 | return left.Equals(right); 44 | } 45 | 46 | public static bool operator !=(Vector3D left, Vector3D right) 47 | { 48 | return !(left == right); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 |  2 | // This file is used by Code Analysis to maintain SuppressMessage 3 | // attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given 5 | // a specific target and scoped to a namespace, type, member, etc. 6 | 7 | using System.Diagnostics.CodeAnalysis; 8 | 9 | [assembly: SuppressMessage("Style", "IDE0017:Simplify object initialization", Justification = "")] 10 | [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "namespaceanddescendants", Target = "ManiaPlanetSharp")] 11 | [assembly: SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "", Scope = "namespaceanddescendants", Target = "ManiaPlanetSharp")] 12 | [assembly: SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "", Scope = "member", Target = "~M:ManiaPlanetSharp.Utilities.MiniLZO.Decompress(System.Byte[],System.Byte[])")] 13 | [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "namespaceanddescendants", Target = "ManiaPlanetSharp.GameBox")] 14 | [assembly: SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "namespaceanddescendants", Target = "ManiaPlanetSharp.GameBox")] 15 | [assembly: SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "", Scope = "namespaceanddescendants", Target = "ManiaPlanetSharp.GameBox.Parsing")] 16 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/ManiaPlanetSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | Stefan Baumann 6 | Stefan Baumann 7 | ManiaPlanetSharp 8 | https://github.com/stefan-baumann/ManiaPlanetSharp 9 | 10 | ManiaPlanet, Trackmania, Shootmania, GameBox, Parser, Metadata, ManiaExchange 11 | Copyright © 2017-2020 Stefan Baumann 12 | true 13 | https://github.com/stefan-baumann/ManiaPlanetSharp 14 | LICENSE 15 | 16 | 17 | 18 | true 19 | DEBUG; HACKY_OBJECT_MODEL_DETECTION 20 | 21 | 22 | 23 | 24 | true 25 | TRACE; HACKY_OBJECT_MODEL_DETECTION 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | all 37 | runtime; build; native; contentfiles; analyzers; buildtransitive 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | True 54 | True 55 | Resources.resx 56 | 57 | 58 | 59 | 60 | 61 | ResXFileCodeGenerator 62 | Resources.Designer.cs 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Dieser Code wurde von einem Tool generiert. 4 | // Laufzeitversion:4.0.30319.42000 5 | // 6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn 7 | // der Code erneut generiert wird. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ManiaPlanetSharp.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. 17 | /// 18 | // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert 19 | // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. 20 | // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen 21 | // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ManiaPlanetSharp.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle 51 | /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Sucht eine lokalisierte Zeichenfolge, die true ähnelt. 65 | /// 66 | internal static string UseImageSharp { 67 | get { 68 | return ResourceManager.GetString("UseImageSharp", resourceCulture); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "ManiaPlanetSharp": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/BlockData.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | 3 | namespace ManiaPlanetSharp.TMUnlimiter 4 | { 5 | public abstract class BlockData 6 | { 7 | public uint BlockIndex { get; private set; } 8 | 9 | public BlockData( uint blockIndex ) 10 | { 11 | this.BlockIndex = blockIndex; 12 | } 13 | 14 | public abstract TrackVersion GetTrackVersion(); 15 | 16 | public virtual uint GetOverOverSizeChunkX() 17 | { 18 | return 0; 19 | } 20 | 21 | public virtual uint GetOverOverSizeChunkY() 22 | { 23 | return 0; 24 | } 25 | 26 | public virtual uint GetOverOverSizeChunkZ() 27 | { 28 | return 0; 29 | } 30 | 31 | public virtual bool IsClassicTerrain() 32 | { 33 | return false; 34 | } 35 | 36 | public virtual bool IsInverted() 37 | { 38 | return false; 39 | } 40 | 41 | public virtual bool IsOffsetApplied() 42 | { 43 | return false; 44 | } 45 | 46 | public virtual bool IsRotationApplied() 47 | { 48 | return false; 49 | } 50 | 51 | public virtual bool IsScaleApplied() 52 | { 53 | return false; 54 | } 55 | 56 | public virtual Vector3D GetOffset() 57 | { 58 | return new Vector3D(); 59 | } 60 | 61 | public virtual Vector3D GetRotation() 62 | { 63 | return new Vector3D(); 64 | } 65 | 66 | public virtual Vector3D GetScale() 67 | { 68 | return new Vector3D( 1.0f, 1.0f, 1.0f ); 69 | } 70 | 71 | public virtual SpawnPointAlterMethod GetSpawnPointAlterMethod() 72 | { 73 | return SpawnPointAlterMethod.None; 74 | } 75 | 76 | public virtual bool IsDynamic() 77 | { 78 | return false; 79 | } 80 | 81 | public virtual bool IsInvisible() 82 | { 83 | return false; 84 | } 85 | 86 | public virtual bool IsCollisionDisabled() 87 | { 88 | return false; 89 | } 90 | 91 | public virtual bool IsInBlockGroup( string blockGroup ) 92 | { 93 | return false; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/ChallengeBackend.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox.Parsing; 2 | using System; 3 | 4 | namespace ManiaPlanetSharp.TMUnlimiter 5 | { 6 | public class ChallengeBackend 7 | { 8 | public VersionBackend VersionBackend { get; set; } 9 | public bool IsLegacyFormat { get; set; } 10 | 11 | public ChallengeBackend( TrackVersion trackVersion ) 12 | { 13 | switch ( trackVersion ) 14 | { 15 | case TrackVersion.Vanilla: 16 | { 17 | this.VersionBackend = new Vanilla.VersionBackend(); 18 | break; 19 | } 20 | case TrackVersion.Unlimiter04: 21 | { 22 | this.VersionBackend = new Version04.VersionBackend(); 23 | break; 24 | } 25 | case TrackVersion.Unlimiter06: 26 | { 27 | this.VersionBackend = new Version06.VersionBackend(); 28 | break; 29 | } 30 | case TrackVersion.Unlimiter07: 31 | { 32 | this.VersionBackend = new Version07.VersionBackend(); 33 | break; 34 | } 35 | case TrackVersion.Unlimiter11: 36 | { 37 | this.VersionBackend = new Version11.VersionBackend(); 38 | break; 39 | } 40 | case TrackVersion.Unlimiter12: 41 | { 42 | this.VersionBackend = new Version12.VersionBackend(); 43 | break; 44 | } 45 | case TrackVersion.Unlimiter13: 46 | { 47 | this.VersionBackend = new Version13.VersionBackend(); 48 | break; 49 | } 50 | case TrackVersion.Unlimiter20: 51 | { 52 | this.VersionBackend = new Version20.VersionBackend(); 53 | break; 54 | } 55 | default: 56 | { 57 | throw new NotSupportedException( $"Unsupported track version = { trackVersion }" ); 58 | } 59 | } 60 | } 61 | 62 | public TrackVersion GetTrackVersion() 63 | { 64 | return this.VersionBackend.GetTrackVersion(); 65 | } 66 | 67 | public void ArchiveOld( GameBoxReader reader ) 68 | { 69 | this.IsLegacyFormat = true; 70 | this.VersionBackend.ArchiveOld( reader ); 71 | } 72 | 73 | public void ArchiveNew( GameBoxReader reader, uint archiveVersion ) 74 | { 75 | this.IsLegacyFormat = false; 76 | this.VersionBackend.ArchiveNew( reader, archiveVersion ); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/DecorationVisibility.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public enum DecorationVisibility 4 | { 5 | Default, 6 | SkyOnly, 7 | WarpOnly, 8 | Nothing, 9 | } 10 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/LegacyMediaClipResource.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public class LegacyMediaClipResource 4 | { 5 | public uint MediaClipIndex { get; private set; } 6 | public object Resource { get; private set; } 7 | 8 | public LegacyMediaClipResource( uint mediaClipIndex, object resource ) 9 | { 10 | this.MediaClipIndex = mediaClipIndex; 11 | this.Resource = resource; 12 | } 13 | 14 | public ParameterSet GetParameterSet() 15 | { 16 | return 17 | ( 18 | this.Resource != null && this.Resource is ParameterSet parameterSet 19 | ? 20 | parameterSet 21 | : 22 | null 23 | ); 24 | } 25 | 26 | public LegacyScript GetLegacyScript() 27 | { 28 | return 29 | ( 30 | this.Resource != null && this.Resource is LegacyScript legacyScript 31 | ? 32 | legacyScript 33 | : 34 | null 35 | ); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/LegacyScript.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public class LegacyScript 4 | { 5 | public readonly byte[] ByteCode; 6 | public readonly LegacyScriptExecutionType ExecutionType; 7 | 8 | public LegacyScript( byte[] byteCode, LegacyScriptExecutionType executionType ) 9 | { 10 | this.ByteCode = byteCode; 11 | this.ExecutionType = executionType; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/LegacyScriptExecutionType.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public enum LegacyScriptExecutionType 4 | { 5 | TriggerOnce, 6 | TriggerInside, 7 | TriggerAlways, 8 | } 9 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Parameter.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public class Parameter 4 | { 5 | public ParameterFunction ParameterFunction { get; private set; } 6 | 7 | public Parameter( ParameterFunction parameterFunction ) 8 | { 9 | this.ParameterFunction = parameterFunction; 10 | } 11 | } 12 | 13 | public class ParameterNumber : Parameter 14 | { 15 | public float Value { get; private set; } 16 | 17 | public ParameterNumber( ParameterFunction parameterFunction, float value ) : base( parameterFunction ) 18 | { 19 | this.Value = value; 20 | } 21 | } 22 | 23 | public class ParameterString : Parameter 24 | { 25 | public string Value { get; private set; } 26 | 27 | public ParameterString( ParameterFunction parameterFunction, string value ) : base( parameterFunction ) 28 | { 29 | this.Value = value; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/ParameterFunction.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public class ParameterFunction 4 | { 5 | public string Name { get; private set; } 6 | public ParameterValueType ValueType { get; private set; } 7 | 8 | public ParameterFunction( string name, ParameterValueType valueType ) 9 | { 10 | this.Name = name; 11 | this.ValueType = valueType; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/ParameterSet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ManiaPlanetSharp.TMUnlimiter 4 | { 5 | public class ParameterSet 6 | { 7 | public List Parameters = new List(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/ParameterValueType.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public enum ParameterValueType 4 | { 5 | None, 6 | Number, 7 | String, 8 | } 9 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/SpawnPointAlterMethod.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public enum SpawnPointAlterMethod 4 | { 5 | None, 6 | Manual, 7 | Automatic, 8 | } 9 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/TrackVersion.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter 2 | { 3 | public enum TrackVersion 4 | { 5 | Vanilla = 0, 6 | Unlimiter04 = 1, 7 | Unlimiter06 = 2, 8 | Unlimiter07 = 3, 9 | Unlimiter11 = 4, 10 | Unlimiter12 = 5, 11 | Unlimiter13 = 6, 12 | Unlimiter20 = 7, 13 | } 14 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Vanilla/VersionBackend.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox.Parsing; 2 | 3 | namespace ManiaPlanetSharp.TMUnlimiter.Vanilla 4 | { 5 | public class VersionBackend : TMUnlimiter.VersionBackend 6 | { 7 | public override TrackVersion GetTrackVersion() 8 | { 9 | return TrackVersion.Vanilla; 10 | } 11 | 12 | public override void ArchiveNew( GameBoxReader reader, uint archiveVersion ) 13 | { 14 | // Vanilla track version does not save anything. 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version04/VersionBackend.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter.Version04 2 | { 3 | public class VersionBackend : TMUnlimiter.VersionBackend 4 | { 5 | public override TrackVersion GetTrackVersion() 6 | { 7 | return TrackVersion.Unlimiter04; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version06/BlockData.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter.Version06 2 | { 3 | public class BlockData : TMUnlimiter.BlockData 4 | { 5 | public uint InternalOverOverSizeChunkX { get; set; } 6 | public uint InternalOverOverSizeChunkY { get; set; } 7 | public uint InternalOverOverSizeChunkZ { get; set; } 8 | public bool InternalIsClassicTerrain { get; set; } 9 | 10 | public BlockData( uint blockIndex ) : base( blockIndex ) {} 11 | 12 | public override TrackVersion GetTrackVersion() 13 | { 14 | return TrackVersion.Unlimiter06; 15 | } 16 | 17 | public override uint GetOverOverSizeChunkX() 18 | { 19 | return this.InternalOverOverSizeChunkX; 20 | } 21 | 22 | public override uint GetOverOverSizeChunkY() 23 | { 24 | return this.InternalOverOverSizeChunkY; 25 | } 26 | 27 | public override uint GetOverOverSizeChunkZ() 28 | { 29 | return this.InternalOverOverSizeChunkZ; 30 | } 31 | 32 | public override bool IsClassicTerrain() 33 | { 34 | return this.InternalIsClassicTerrain; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version06/VersionBackend.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter.Version06 2 | { 3 | public class VersionBackend : TMUnlimiter.VersionBackend 4 | { 5 | public override TrackVersion GetTrackVersion() 6 | { 7 | return TrackVersion.Unlimiter06; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version07/BlockData.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter.Version07 2 | { 3 | public class BlockData : TMUnlimiter.BlockData 4 | { 5 | public uint InternalOverOverSizeChunkX { get; set; } 6 | public uint InternalOverOverSizeChunkY { get; set; } 7 | public uint InternalOverOverSizeChunkZ { get; set; } 8 | public bool InternalIsClassicTerrain { get; set; } 9 | public bool InternalIsInverted { get; set; } 10 | 11 | public BlockData( uint blockIndex ) : base( blockIndex ) {} 12 | 13 | public override TrackVersion GetTrackVersion() 14 | { 15 | return TrackVersion.Unlimiter07; 16 | } 17 | 18 | public override uint GetOverOverSizeChunkX() 19 | { 20 | return this.InternalOverOverSizeChunkX; 21 | } 22 | 23 | public override uint GetOverOverSizeChunkY() 24 | { 25 | return this.InternalOverOverSizeChunkY; 26 | } 27 | 28 | public override uint GetOverOverSizeChunkZ() 29 | { 30 | return this.InternalOverOverSizeChunkZ; 31 | } 32 | 33 | public override bool IsClassicTerrain() 34 | { 35 | return this.InternalIsClassicTerrain; 36 | } 37 | 38 | public override bool IsInverted() 39 | { 40 | return this.InternalIsInverted; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version07/VersionBackend.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter.Version07 2 | { 3 | public class VersionBackend : TMUnlimiter.VersionBackend 4 | { 5 | public override TrackVersion GetTrackVersion() 6 | { 7 | return TrackVersion.Unlimiter07; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version11/BlockData.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | 3 | namespace ManiaPlanetSharp.TMUnlimiter.Version11 4 | { 5 | public class BlockData : TMUnlimiter.BlockData 6 | { 7 | public uint InternalOverOverSizeChunkX { get; set; } 8 | public uint InternalOverOverSizeChunkY { get; set; } 9 | public uint InternalOverOverSizeChunkZ { get; set; } 10 | public bool InternalIsClassicTerrain { get; set; } 11 | public bool InternalIsInverted { get; set; } 12 | public int InternalBlockOffsetX { get; set; } 13 | public int InternalBlockOffsetY { get; set; } 14 | public int InternalBlockOffsetZ { get; set; } 15 | public uint InternalBlockRotationX { get; set; } 16 | public uint InternalBlockRotationY { get; set; } 17 | public uint InternalBlockRotationZ { get; set; } 18 | 19 | public BlockData( uint blockIndex ) : base( blockIndex ) {} 20 | 21 | public override TrackVersion GetTrackVersion() 22 | { 23 | return TrackVersion.Unlimiter11; 24 | } 25 | 26 | public override uint GetOverOverSizeChunkX() 27 | { 28 | return this.InternalOverOverSizeChunkX; 29 | } 30 | 31 | public override uint GetOverOverSizeChunkY() 32 | { 33 | return this.InternalOverOverSizeChunkY; 34 | } 35 | 36 | public override uint GetOverOverSizeChunkZ() 37 | { 38 | return this.InternalOverOverSizeChunkZ; 39 | } 40 | 41 | public override bool IsClassicTerrain() 42 | { 43 | return this.InternalIsClassicTerrain; 44 | } 45 | 46 | public override bool IsInverted() 47 | { 48 | return this.InternalIsInverted; 49 | } 50 | 51 | public override bool IsOffsetApplied() 52 | { 53 | return this.InternalBlockOffsetX != 0 || this.InternalBlockOffsetY != 0 || this.InternalBlockOffsetZ != 0; 54 | } 55 | 56 | public override bool IsRotationApplied() 57 | { 58 | return this.InternalBlockRotationX != 0 || this.InternalBlockRotationY != 0 || this.InternalBlockRotationZ != 0; 59 | } 60 | 61 | public override Vector3D GetOffset() 62 | { 63 | return new Vector3D( this.InternalBlockOffsetX, this.InternalBlockOffsetY, this.InternalBlockOffsetZ ); 64 | } 65 | 66 | public override Vector3D GetRotation() 67 | { 68 | return new Vector3D( this.InternalBlockRotationX * 5, this.InternalBlockRotationY * 5, this.InternalBlockRotationZ * 5 ); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version12/BlockData.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | 3 | namespace ManiaPlanetSharp.TMUnlimiter.Version12 4 | { 5 | public class BlockData : TMUnlimiter.BlockData 6 | { 7 | public uint InternalOverOverSizeChunkX { get; set; } 8 | public uint InternalOverOverSizeChunkY { get; set; } 9 | public uint InternalOverOverSizeChunkZ { get; set; } 10 | public bool InternalIsClassicTerrain { get; set; } 11 | public bool InternalIsInverted { get; set; } 12 | public int InternalBlockOffsetX { get; set; } 13 | public int InternalBlockOffsetY { get; set; } 14 | public int InternalBlockOffsetZ { get; set; } 15 | public uint InternalBlockRotationX { get; set; } 16 | public uint InternalBlockRotationY { get; set; } 17 | public uint InternalBlockRotationZ { get; set; } 18 | 19 | public BlockData( uint blockIndex ) : base( blockIndex ) {} 20 | 21 | public override TrackVersion GetTrackVersion() 22 | { 23 | return TrackVersion.Unlimiter12; 24 | } 25 | 26 | public override uint GetOverOverSizeChunkX() 27 | { 28 | return this.InternalOverOverSizeChunkX; 29 | } 30 | 31 | public override uint GetOverOverSizeChunkY() 32 | { 33 | return this.InternalOverOverSizeChunkY; 34 | } 35 | 36 | public override uint GetOverOverSizeChunkZ() 37 | { 38 | return this.InternalOverOverSizeChunkZ; 39 | } 40 | 41 | public override bool IsClassicTerrain() 42 | { 43 | return this.InternalIsClassicTerrain; 44 | } 45 | 46 | public override bool IsInverted() 47 | { 48 | return this.InternalIsInverted; 49 | } 50 | 51 | public override bool IsOffsetApplied() 52 | { 53 | return this.InternalBlockOffsetX != 0 || this.InternalBlockOffsetY != 0 || this.InternalBlockOffsetZ != 0; 54 | } 55 | 56 | public override bool IsRotationApplied() 57 | { 58 | return this.InternalBlockRotationX != 0 || this.InternalBlockRotationY != 0 || this.InternalBlockRotationZ != 0; 59 | } 60 | 61 | public override Vector3D GetOffset() 62 | { 63 | return new Vector3D( this.InternalBlockOffsetX * 0.1f, this.InternalBlockOffsetY * 0.1f, this.InternalBlockOffsetZ * 0.1f ); 64 | } 65 | 66 | public override Vector3D GetRotation() 67 | { 68 | return new Vector3D( this.InternalBlockRotationX * 0.1f, this.InternalBlockRotationY * 0.1f, this.InternalBlockRotationZ * 0.1f ); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version13/BlockData.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox; 2 | 3 | namespace ManiaPlanetSharp.TMUnlimiter.Version13 4 | { 5 | public class BlockData : TMUnlimiter.BlockData 6 | { 7 | public uint InternalOverOverSizeChunkX { get; set; } 8 | public uint InternalOverOverSizeChunkY { get; set; } 9 | public uint InternalOverOverSizeChunkZ { get; set; } 10 | public bool InternalIsClassicTerrain { get; set; } 11 | public bool InternalIsInverted { get; set; } 12 | public Vector3D InternalBlockOffset { get; set; } = new Vector3D(); 13 | public Vector3D InternalBlockRotation { get; set; } = new Vector3D(); 14 | public Vector3D InternalBlockScale { get; set; } = new Vector3D( 1.0f, 1.0f, 1.0f ); 15 | public bool InternalIsSpawnPointFixEnabled { get; set; } 16 | public bool InternalIsDynamic { get; set; } 17 | public bool InternalIsInvisible { get; set; } 18 | public bool InternalIsCollisionDisabled { get; set; } 19 | public string InternalBlockGroup { get; set; } 20 | 21 | public BlockData( uint blockIndex ) : base( blockIndex ) {} 22 | 23 | public override TrackVersion GetTrackVersion() 24 | { 25 | return TrackVersion.Unlimiter13; 26 | } 27 | 28 | public override uint GetOverOverSizeChunkX() 29 | { 30 | return this.InternalOverOverSizeChunkX; 31 | } 32 | 33 | public override uint GetOverOverSizeChunkY() 34 | { 35 | return this.InternalOverOverSizeChunkY; 36 | } 37 | 38 | public override uint GetOverOverSizeChunkZ() 39 | { 40 | return this.InternalOverOverSizeChunkZ; 41 | } 42 | 43 | public override bool IsClassicTerrain() 44 | { 45 | return this.InternalIsClassicTerrain; 46 | } 47 | 48 | public override bool IsInverted() 49 | { 50 | return this.InternalIsInverted; 51 | } 52 | 53 | public override bool IsOffsetApplied() 54 | { 55 | return this.InternalBlockOffset.X != 0 || this.InternalBlockOffset.Y != 0 || this.InternalBlockOffset.Z != 0; 56 | } 57 | 58 | public override bool IsRotationApplied() 59 | { 60 | return this.InternalBlockRotation.X != 0 || this.InternalBlockRotation.Y != 0 || this.InternalBlockRotation.Z != 0; 61 | } 62 | 63 | public override bool IsScaleApplied() 64 | { 65 | return this.InternalBlockScale.X != 1 || this.InternalBlockScale.Y != 1 || this.InternalBlockScale.Z != 1; 66 | } 67 | 68 | public override Vector3D GetOffset() 69 | { 70 | return new Vector3D( this.InternalBlockOffset.X, this.InternalBlockOffset.Y, this.InternalBlockOffset.Z ); 71 | } 72 | 73 | public override Vector3D GetRotation() 74 | { 75 | return new Vector3D( this.InternalBlockRotation.X, this.InternalBlockRotation.Y, this.InternalBlockRotation.Z ); 76 | } 77 | 78 | public override Vector3D GetScale() 79 | { 80 | return new Vector3D( this.InternalBlockScale.X, this.InternalBlockScale.Y, this.InternalBlockScale.Z ); 81 | } 82 | 83 | public override SpawnPointAlterMethod GetSpawnPointAlterMethod() 84 | { 85 | return this.InternalIsSpawnPointFixEnabled ? SpawnPointAlterMethod.Automatic : SpawnPointAlterMethod.None; 86 | } 87 | 88 | public override bool IsDynamic() 89 | { 90 | return this.InternalIsDynamic; 91 | } 92 | 93 | public override bool IsInvisible() 94 | { 95 | return this.InternalIsInvisible; 96 | } 97 | 98 | public override bool IsCollisionDisabled() 99 | { 100 | return this.InternalIsCollisionDisabled; 101 | } 102 | 103 | public override bool IsInBlockGroup( string blockGroup ) 104 | { 105 | return this.InternalBlockGroup != null && this.InternalBlockGroup == blockGroup; 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version13/BlockFlags.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter.Version13 2 | { 3 | [System.Flags] 4 | enum BlockFlags : ushort 5 | { 6 | IsOutsideBoundaries = 1 << 0, 7 | IsMoved = 1 << 1, 8 | IsRotated = 1 << 2, 9 | IsScaled = 1 << 3, 10 | IsInverted = 1 << 4, 11 | IsVanillaTerrain = 1 << 5, 12 | IsSpawnPointFixEnabled = 1 << 6, 13 | IsDynamic = 1 << 7, 14 | IsInvisible = 1 << 8, 15 | IsCollisionDisabled = 1 << 9, 16 | IsClassicMode = 1 << 10, 17 | IsClassicTerrain = 1 << 11, 18 | HasIdentifier = 1 << 14, 19 | Reserved = 1 << 15, 20 | } 21 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version13/ChallengeFlags.cs: -------------------------------------------------------------------------------- 1 | namespace ManiaPlanetSharp.TMUnlimiter.Version13 2 | { 3 | [System.Flags] 4 | enum ChallengeFlags : ushort 5 | { 6 | DecorationVisibility_SkyOnly = 1 << 0, 7 | IsDecorationMoved = 1 << 1, 8 | DecorationVisibility_Nothing = 1 << 2, 9 | IsDecorationScaled = 1 << 3, 10 | IsTrackBaseEmpty = 1 << 4, 11 | IsVanillaMode = 1 << 5, 12 | DecorationVisibility_Warp = 1 << 8, 13 | IsPylonsDisabled = 1 << 9, 14 | ReservedBit = 1 << 15, 15 | }; 16 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/TMUnlimiter/Version20/VersionBackend.cs: -------------------------------------------------------------------------------- 1 | using ManiaPlanetSharp.GameBox.Parsing; 2 | 3 | namespace ManiaPlanetSharp.TMUnlimiter.Version20 4 | { 5 | public class VersionBackend : TMUnlimiter.VersionBackend 6 | { 7 | public override TrackVersion GetTrackVersion() 8 | { 9 | return TrackVersion.Unlimiter20; 10 | } 11 | 12 | #pragma warning disable CA1062 // Validate arguments of public methods -- Reader is always guaranteed to be non-null. 13 | public override void ArchiveNew( GameBoxReader reader, uint archiveVersion ) 14 | { 15 | // No need to implement this chunk (at the moment) 16 | } 17 | #pragma warning restore CA1062 // Validate arguments of public methods -- Reader is always guaranteed to be non-null. 18 | } 19 | } -------------------------------------------------------------------------------- /src/ManiaPlanetSharp/Utilities/IndentingStringBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ManiaPlanetSharp.Utilities 6 | { 7 | public class IndentingStringBuilder 8 | { 9 | public IndentingStringBuilder(string indentation = " ") 10 | { 11 | this.Indentation = indentation; 12 | } 13 | 14 | public string Indentation { get; protected set; } 15 | 16 | protected StringBuilder Builder { get; private set; } = new StringBuilder(); 17 | 18 | public int IndentationLevel { get; set; } = 0; 19 | 20 | public void AppendLine(string value) 21 | { 22 | for (int i = 0; i < this.IndentationLevel; i++) 23 | { 24 | this.Builder.Append(this.Indentation); 25 | } 26 | this.Builder.AppendLine(value); 27 | } 28 | 29 | public override string ToString() 30 | { 31 | return this.Builder.ToString(); 32 | } 33 | 34 | public void Indent() 35 | { 36 | this.IndentationLevel++; 37 | } 38 | 39 | public void UnIndent() 40 | { 41 | if (this.IndentationLevel <= 0) 42 | { 43 | throw new InvalidOperationException(); 44 | } 45 | this.IndentationLevel--; 46 | } 47 | } 48 | } 49 | --------------------------------------------------------------------------------