├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── UnturnedMapMergeTool.jpg ├── UnturnedMapMergeTool.sln └── UnturnedMapMergeTool ├── Abstractions ├── DataMergeToolBase.cs └── IDataMergeTool.cs ├── Config.cs ├── DataMergeTools ├── BoundsDataMergeTool.cs ├── BuildablesDataMergeTool.cs ├── FlagsDataMergeTool.cs ├── NavigationsDataMergeTool.cs ├── NodesDataMergeTool.cs ├── ObjectsDataMergeTool.cs ├── PathsDataMergeTool.cs ├── RoadsDataMergeTool.cs ├── Spawns │ ├── AnimalsDataMergeTool.cs │ ├── FaunaDataMergeTool.cs │ ├── ItemsDataMergeTool.cs │ ├── JarsDataMergeTool.cs │ ├── PlayersDataMergeTool.cs │ ├── VehiclesDataMergeTool.cs │ └── ZombiesDataMergeTool.cs └── TreesDataMergeTool.cs ├── Extensions └── StringExtensions.cs ├── Helpers └── TilesHelper.cs ├── Models ├── Configs │ ├── CopyMapConfig.cs │ └── OutputMapConfig.cs ├── Contents │ ├── Animals │ │ ├── ZombieRegionData.cs │ │ └── ZombieSpawnpointData.cs │ ├── AnimalsDataContent.cs │ ├── Bounds │ │ └── BoundData.cs │ ├── BoundsDataContent.cs │ ├── BuildableDataContent.cs │ ├── Buildables │ │ ├── BuildableData.cs │ │ └── BuildableRegionData.cs │ ├── FaunaDataContent.cs │ ├── Faunas │ │ ├── AnimalSpawnData.cs │ │ ├── AnimalSpawnpointData.cs │ │ ├── AnimalTableData.cs │ │ └── AnimalTierData.cs │ ├── Flags │ │ └── FlagData.cs │ ├── FlagsData │ │ └── FlagDataData.cs │ ├── FlagsDataContent.cs │ ├── FlagsDataDataContent.cs │ ├── Items │ │ ├── ItemSpawnData.cs │ │ ├── ItemTableData.cs │ │ └── ItemTierData.cs │ ├── ItemsDataContent.cs │ ├── Jars │ │ ├── ItemRegionData.cs │ │ └── ItemSpawnpointData.cs │ ├── JarsDataContent.cs │ ├── Navigations │ │ ├── NavmeshTileData.cs │ │ └── NavmeshTileVertData.cs │ ├── NavigationsDataContent.cs │ ├── Nodes │ │ ├── LocationNodeData.cs │ │ ├── NodeData.cs │ │ ├── PurchaseNodeData.cs │ │ └── SafezoneNodeData.cs │ ├── NodesDataContent.cs │ ├── ObjectDataContent.cs │ ├── Objects │ │ ├── ObjectData.cs │ │ └── ObjectRegionData.cs │ ├── Paths │ │ ├── PathJointData.cs │ │ └── PathLineData.cs │ ├── PathsDataContent.cs │ ├── Players │ │ └── PlayerSpawnData.cs │ ├── PlayersDataContent.cs │ ├── Roads │ │ └── RoadMaterialData.cs │ ├── RoadsDataContent.cs │ ├── Trees │ │ ├── TreeData.cs │ │ └── TreeRegionData.cs │ ├── TreesDataContent.cs │ ├── Vehicles │ │ ├── VehicleSpawnData.cs │ │ ├── VehicleSpawnpointData.cs │ │ ├── VehicleTableData.cs │ │ └── VehicleTierData.cs │ ├── VehiclesDataContent.cs │ ├── Zombies │ │ ├── ZombieClothData.cs │ │ ├── ZombieSlotData.cs │ │ └── ZombieTableData.cs │ └── ZombiesDataContent.cs ├── Coordinate.cs ├── CopyMapData.cs ├── Enums │ ├── EMapSize.cs │ └── ETileType.cs └── TileFileInfo.cs ├── Program.cs ├── Services ├── CopyMap.Logs.cs ├── CopyMap.Tiles.cs ├── CopyMap.cs ├── OutputMap.Helpers.cs └── OutputMap.cs ├── Unturned ├── Block.cs ├── GuidBuffer.cs ├── Hash.cs ├── MathfEx.cs ├── Regions.cs ├── River.cs ├── Types.cs └── Unity │ ├── CSteamID.cs │ ├── Color.cs │ ├── EulerAngles.cs │ ├── Mathf.cs │ └── Vector3.cs ├── UnturnedMapMergeTool.csproj └── config.json /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Restore Monarchy 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unturned Map Merge Tool 2 | Program for merging multiple unturned maps into one. 3 | 4 | ## Information 5 | The tool is hard to use and it's not always kept up-to-date with the current version of Unturned. 6 | We do not provide any documentation or instructions on how to use the tool. 7 | 8 | ### We offer to merge maps for you for a small fee. 9 | Join our Discord and create a ticket there. Provide a list of maps you want to merge and info how to arrange them. We charge **$30 USD fee** per merge. 10 | We only merge the maps using our tool, but we don't finish the maps. In order to make the map playable, you need to finish it yourself or hire someone to do it for you. 11 | 12 | [Discord Invite Link](https://discord.com/invite/KZv8VSKQqQ) 13 | 14 | ## Some maps created using this tool 15 | * [Triple Classic (Peyukton)](https://steamcommunity.com/sharedfiles/filedetails/?id=2867004062) by [adLay](https://steamcommunity.com/profiles/76561199059647240) 16 | * [AMIO (All Maps in One)](https://steamcommunity.com/workshop/filedetails/?id=2877846948) by [landsQuid](https://steamcommunity.com/id/BearFlewOverTheOcean) 17 | * [Trilogy (Triple Classic Remastered)](https://steamcommunity.com/sharedfiles/filedetails/?id=2876376295) by [landsQuid](https://steamcommunity.com/id/BearFlewOverTheOcean) 18 | * [Anomaly](https://steamcommunity.com/workshop/filedetails/?id=2880116065) by [landsQuid](https://steamcommunity.com/id/BearFlewOverTheOcean) 19 | 20 | ## Currently Mergeable Files 21 | Landscape merge works by renaming and copying the files from the original map. 22 | All of the `.dat` files I'm reading into objects, shifting the positions inside the files, combining and then saving into the output map directory. 23 | 24 | **Landscape** 25 | * Heightmaps/* 26 | * Holes/* 27 | * Splatmaps/* 28 | 29 | **Spawns** 30 | * Fauna.dat 31 | * Items.dat 32 | * Jars.dat 33 | * Players.dat 34 | * Vehicles.dat 35 | * Zombies.dat 36 | 37 | **Environment** 38 | * Bounds.dat 39 | * Flags.dat 40 | * Flags_Data.dat 41 | * Nodes.dat 42 | * Paths.dat 43 | * Roads.dat 44 | 45 | **Terrain** 46 | * Trees.dat 47 | 48 | **Level** 49 | * Buildables.dat 50 | * Objects.dat 51 | 52 | ### Example board for the insane size map 53 | This is an example board used to get right coordinates for the map you want to be generated from another. 54 | 55 | ![](UnturnedMapMergeTool.jpg) 56 | 57 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RestoreMonarchy/UnturnedMapMergeTool/bd855074ca77946eef355bb6bbf7f7fecb3208f5/UnturnedMapMergeTool.jpg -------------------------------------------------------------------------------- /UnturnedMapMergeTool.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32825.248 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnturnedMapMergeTool", "UnturnedMapMergeTool\UnturnedMapMergeTool.csproj", "{BE2766E6-1123-4288-A910-CB04B3AC4254}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6492AFA7-E336-4BC6-BC34-F45A818636FB}" 9 | ProjectSection(SolutionItems) = preProject 10 | README.md = README.md 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {BE2766E6-1123-4288-A910-CB04B3AC4254}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {BE2766E6-1123-4288-A910-CB04B3AC4254}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {BE2766E6-1123-4288-A910-CB04B3AC4254}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {BE2766E6-1123-4288-A910-CB04B3AC4254}.Release|Any CPU.Build.0 = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | GlobalSection(ExtensibilityGlobals) = postSolution 28 | SolutionGuid = {1B4644FD-C639-426C-9B87-C09C227C197B} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Abstractions/DataMergeToolBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnturnedMapMergeTool.Services; 3 | 4 | namespace UnturnedMapMergeTool.Abstractions 5 | { 6 | public abstract class DataMergeToolBase : IDataMergeTool 7 | { 8 | public abstract void CombineAndSaveData(OutputMap outputMap); 9 | 10 | public abstract void ReadData(CopyMap copyMap); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Abstractions/IDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Services; 2 | 3 | namespace UnturnedMapMergeTool.Abstractions 4 | { 5 | public interface IDataMergeTool 6 | { 7 | void ReadData(CopyMap copyMap); 8 | void CombineAndSaveData(OutputMap outputMap); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Config.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnturnedMapMergeTool.Models.Enums; 7 | using UnturnedMapMergeTool.Models.Configs; 8 | using UnturnedMapMergeTool.Models; 9 | 10 | namespace UnturnedMapMergeTool 11 | { 12 | public class Config 13 | { 14 | public void LoadDefaultValues() 15 | { 16 | Maps = new() 17 | { 18 | new CopyMapConfig() 19 | { 20 | Name = "PEI", 21 | Path = "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Unturned\\Maps\\PEI", 22 | Size = EMapSize.Medium, 23 | WithBorders = false, 24 | StartCoordinate = new Coordinate() 25 | { 26 | X = 1, 27 | Y = 1 28 | }, 29 | ShiftX = -2048, 30 | ShiftY = -2048, 31 | IgnoreAirdropNodes = false 32 | }, 33 | new CopyMapConfig() 34 | { 35 | Name = "Washington", 36 | Path = "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Unturned\\Maps\\Washington", 37 | Size = EMapSize.Medium, 38 | WithBorders = true, 39 | StartCoordinate = new Coordinate() 40 | { 41 | X = 5, 42 | Y = 3 43 | }, 44 | ShiftX = 2048, 45 | ShiftY = 0, 46 | IgnoreAirdropNodes = false 47 | } 48 | }; 49 | 50 | OutputMap = new() 51 | { 52 | Path = "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Unturned\\Maps\\MergedMaps" 53 | }; 54 | } 55 | 56 | 57 | public List Maps { get; set; } 58 | 59 | public OutputMapConfig OutputMap { get; set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/BoundsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.IO; 4 | using UnturnedMapMergeTool.Abstractions; 5 | using UnturnedMapMergeTool.Models.Contents; 6 | using UnturnedMapMergeTool.Models; 7 | using UnturnedMapMergeTool.Services; 8 | using System.Collections.Generic; 9 | using UnturnedMapMergeTool.Models.Contents.Bounds; 10 | using System.Linq; 11 | using UnturnedMapMergeTool.Models.Contents.FlagsData; 12 | 13 | namespace UnturnedMapMergeTool.DataMergeTools 14 | { 15 | public class BoundsDataMergeTool : DataMergeToolBase 16 | { 17 | private List> Data { get; set; } = new(); 18 | 19 | public override void CombineAndSaveData(OutputMap outputMap) 20 | { 21 | byte saveDataVersion = 1; 22 | byte count = (byte)Data.Sum(x => x.Content.Bounds.Count); 23 | 24 | BoundsDataContent content = new(saveDataVersion, count); 25 | 26 | foreach (CopyMapData dataItem in Data) 27 | { 28 | foreach (BoundData bound in dataItem.Content.Bounds) 29 | { 30 | if (dataItem.CopyMap.IsOriginalPositionBypassed(bound.Center)) 31 | { 32 | continue; 33 | } 34 | 35 | dataItem.CopyMap.ApplyPositionShift(bound.Center); 36 | content.Bounds.Add(bound); 37 | } 38 | } 39 | 40 | string savePath = outputMap.CombinePath("Environment/Bounds.dat"); 41 | 42 | content.SaveToFile(savePath); 43 | 44 | // DEBUG 45 | File.WriteAllText($"bounds_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 46 | 47 | Log.Information($"Combined and saved {content.Bounds.Count} bounds"); 48 | } 49 | 50 | public override void ReadData(CopyMap copyMap) 51 | { 52 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Environment/Bounds.dat"); 53 | BoundsDataContent content = BoundsDataContent.FromFile(fileNamePath); 54 | 55 | // Write to JSON file for debug 56 | File.WriteAllText($"bounds_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 57 | 58 | CopyMapData dataItem = new() 59 | { 60 | CopyMap = copyMap, 61 | Content = content 62 | }; 63 | 64 | Data.Add(dataItem); 65 | 66 | Log.Information($"Read {content.Bounds.Count} bounds"); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/BuildablesDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using UnturnedMapMergeTool.Abstractions; 7 | using UnturnedMapMergeTool.Models; 8 | using UnturnedMapMergeTool.Models.Contents; 9 | using UnturnedMapMergeTool.Models.Contents.Buildables; 10 | using UnturnedMapMergeTool.Services; 11 | using UnturnedMapMergeTool.Unturned; 12 | 13 | namespace UnturnedMapMergeTool.DataMergeTools 14 | { 15 | public class BuildablesDataMergeTool : DataMergeToolBase 16 | { 17 | private List> Data { get; set; } = new(); 18 | 19 | public override void CombineAndSaveData(OutputMap outputMap) 20 | { 21 | byte saveDataVersion = 10; 22 | BuildableDataContent content = new(saveDataVersion); 23 | 24 | foreach (CopyMapData dataItem in Data) 25 | { 26 | IEnumerable copyMapBuildables = dataItem.Content.BuildableRegions.SelectMany(x => x.Buildables); 27 | 28 | foreach (BuildableData buildableData in copyMapBuildables) 29 | { 30 | BuildableData shiftedBuildableData = new() 31 | { 32 | Position = buildableData.Position, 33 | AssetId = buildableData.AssetId, 34 | Rotation = buildableData.Rotation 35 | }; 36 | 37 | // Yeah Y is actually Z in unity Vector3 38 | shiftedBuildableData.Position.x += dataItem.CopyMap.Config.ShiftX; 39 | shiftedBuildableData.Position.z += dataItem.CopyMap.Config.ShiftY; 40 | 41 | Regions.tryGetCoordinate(shiftedBuildableData.Position, out byte regionX, out byte regionY); 42 | 43 | BuildableRegionData objectRegionData = content.BuildableRegions.FirstOrDefault(x => x.RegionX == regionX && x.RegionY == regionY); 44 | 45 | if (objectRegionData == null) 46 | { 47 | Log.Warning("Object region not found for the shifted region X: {0} Y: {1}", regionX, regionY); 48 | continue; 49 | } 50 | 51 | objectRegionData.Buildables.Add(shiftedBuildableData); 52 | objectRegionData.Count++; 53 | } 54 | } 55 | 56 | string objectsSavePath = outputMap.CombinePath("Level/Buildables.dat"); 57 | 58 | content.SaveToFile(objectsSavePath); 59 | 60 | Log.Information($"Combined and saved {content.BuildableRegions.Sum(x => x.Count)} buildables"); 61 | } 62 | 63 | public override void ReadData(CopyMap copyMap) 64 | { 65 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Level/Buildables.dat"); 66 | BuildableDataContent content = BuildableDataContent.FromFile(fileNamePath); 67 | 68 | File.WriteAllText($"buildables_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 69 | 70 | CopyMapData dataItem = new() 71 | { 72 | CopyMap = copyMap, 73 | Content = content 74 | }; 75 | Data.Add(dataItem); 76 | 77 | int buildablesCount = content.BuildableRegions.Sum(x => x.Count); 78 | Log.Information($"Read {buildablesCount} buildables"); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/FlagsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection.Metadata; 8 | using UnturnedMapMergeTool.Abstractions; 9 | using UnturnedMapMergeTool.Models; 10 | using UnturnedMapMergeTool.Models.Contents; 11 | using UnturnedMapMergeTool.Models.Contents.Flags; 12 | using UnturnedMapMergeTool.Models.Contents.FlagsData; 13 | using UnturnedMapMergeTool.Models.Contents.Nodes; 14 | using UnturnedMapMergeTool.Services; 15 | 16 | namespace UnturnedMapMergeTool.DataMergeTools 17 | { 18 | public class FlagsDataMergeTool : DataMergeToolBase 19 | { 20 | public List> Flags { get; set; } = new(); 21 | private List> FlagsData { get; set; } = new(); 22 | 23 | private int flagsIndex = 0; 24 | 25 | public override void CombineAndSaveData(OutputMap outputMap) 26 | { 27 | byte flagsSaveVersion = 4; 28 | byte flagsDataSaveVersion = 5; 29 | 30 | FlagsDataContent flagsContent = new(flagsSaveVersion, 0); 31 | FlagsDataDataContent flagsDataContent = new(flagsDataSaveVersion, 0); 32 | 33 | foreach (CopyMapData flagItem in Flags) 34 | { 35 | // If this throws an exception it means something is not cool 36 | CopyMapData flagDataItem = FlagsData.First(x => x.CopyMap == flagItem.CopyMap); 37 | 38 | if (flagDataItem.Content.FlagsData.Count != flagItem.Content.Flags.Count) 39 | { 40 | flagDataItem.Content.FlagsData.RemoveAt(FlagsData.Count - 1); 41 | //throw new Exception("Flags data count and flags count should be the same"); 42 | } 43 | 44 | for (int i = 0; i < flagItem.Content.Count; i++) 45 | { 46 | FlagData flag = flagItem.Content.Flags[i]; 47 | FlagDataData flagData = flagDataItem.Content.FlagsData[i]; 48 | 49 | if (flagItem.CopyMap.IsOriginalPositionBypassed(flag.Point)) 50 | { 51 | continue; 52 | } 53 | 54 | flagItem.CopyMap.ApplyPositionShift(flag.Point); 55 | 56 | if (flagItem.CopyMap.IsOutputMapBorder(flag.Point)) 57 | { 58 | continue; 59 | } 60 | 61 | flagsContent.Flags.Add(flag); 62 | flagsDataContent.FlagsData.Add(flagData); 63 | } 64 | } 65 | 66 | flagsContent.Count = (byte)flagsContent.Flags.Count; 67 | flagsDataContent.Count = (byte)flagsDataContent.FlagsData.Count; 68 | 69 | string flagsSavePath = outputMap.CombinePath("Environment/Flags.dat"); 70 | flagsContent.SaveToFile(flagsSavePath); 71 | File.WriteAllText($"flags_output.json", JsonConvert.SerializeObject(flagsContent, Formatting.Indented)); 72 | Log.Information($"Combined and saved {flagsContent.Flags.Count} flags"); 73 | 74 | string FlagsDataSavePath = outputMap.CombinePath("Environment/Flags_Data.dat"); 75 | flagsDataContent.SaveToFile(FlagsDataSavePath); 76 | File.WriteAllText($"flags_data_output.json", JsonConvert.SerializeObject(flagsDataContent, Formatting.Indented)); 77 | Log.Information($"Combined and saved {flagsDataContent.FlagsData.Count} flags data"); 78 | } 79 | 80 | public override void ReadData(CopyMap copyMap) 81 | { 82 | ReadFlags(copyMap); 83 | ReadFlagsData(copyMap); 84 | } 85 | 86 | private void ReadFlags(CopyMap copyMap) 87 | { 88 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Environment/Flags.dat"); 89 | FlagsDataContent content = FlagsDataContent.FromFile(fileNamePath); 90 | 91 | // Write to JSON file for debug 92 | File.WriteAllText($"flags_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 93 | 94 | // Add flag to the copy maps because it will be used by the navigation 95 | copyMap.Flags = new(); 96 | copyMap.FlagsStartIndex = flagsIndex; 97 | foreach (FlagData flag in content.Flags) 98 | { 99 | copyMap.Flags.Add(flag); 100 | flagsIndex++; 101 | } 102 | 103 | CopyMapData dataItem = new() 104 | { 105 | CopyMap = copyMap, 106 | Content = content 107 | }; 108 | 109 | Flags.Add(dataItem); 110 | 111 | Log.Information($"Read {content.Flags.Count} flags"); 112 | } 113 | 114 | public void ReadFlagsData(CopyMap copyMap) 115 | { 116 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Environment/Flags_Data.dat"); 117 | FlagsDataDataContent content = FlagsDataDataContent.FromFile(fileNamePath); 118 | 119 | // Write to JSON file for debug 120 | File.WriteAllText($"flags_data_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 121 | 122 | CopyMapData dataItem = new() 123 | { 124 | CopyMap = copyMap, 125 | Content = content 126 | }; 127 | 128 | FlagsData.Add(dataItem); 129 | 130 | Log.Information($"Read {content.FlagsData.Count} flags data"); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/NavigationsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using UnturnedMapMergeTool.Abstractions; 7 | using UnturnedMapMergeTool.Models; 8 | using UnturnedMapMergeTool.Models.Contents; 9 | using UnturnedMapMergeTool.Services; 10 | 11 | namespace UnturnedMapMergeTool.DataMergeTools 12 | { 13 | public class NavigationsDataMergeTool : DataMergeToolBase 14 | { 15 | private List>> Data { get; set; } = new(); 16 | 17 | public override void CombineAndSaveData(OutputMap outputMap) 18 | { 19 | int count = 0; 20 | foreach (CopyMapData> dataItem in Data) 21 | { 22 | for (int i = 0; i < dataItem.Content.Count; i++) 23 | { 24 | NavigationsDataContent content = dataItem.Content[i]; 25 | if (dataItem.CopyMap.IsOriginalPositionBypassed(content.ForcedBoundsCenter)) 26 | { 27 | continue; 28 | } 29 | 30 | dataItem.CopyMap.ApplyPositionShift(content.ForcedBoundsCenter); 31 | 32 | int index = dataItem.CopyMap.FlagsStartIndex + i; 33 | string savePath = outputMap.CombinePath($"Environment/Navigation_{index}.dat"); 34 | 35 | content.SaveToFile(savePath); 36 | count++; 37 | } 38 | } 39 | 40 | Log.Information($"Combined and saved {count} navigations"); 41 | } 42 | 43 | public override void ReadData(CopyMap copyMap) 44 | { 45 | List dataContents = new(); 46 | 47 | for (int i = 0; i < copyMap.Flags.Count; i++) 48 | { 49 | Stopwatch stopwatch = new(); 50 | stopwatch.Start(); 51 | string fileNamePath = Path.Combine(copyMap.Config.Path, $"Environment/Navigation_{i}.dat"); 52 | NavigationsDataContent content = NavigationsDataContent.FromFile(fileNamePath); 53 | dataContents.Add(content); 54 | stopwatch.Stop(); 55 | 56 | Log.Debug($"Read {content.NavmeshTiles.Length} navmesh tiles from {Path.GetFileName(fileNamePath)} in {stopwatch.Elapsed.TotalSeconds} seconds"); 57 | // Write to JSON file for debug 58 | File.WriteAllText($"navigation_{i}_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 59 | } 60 | 61 | CopyMapData> dataItem = new() 62 | { 63 | CopyMap = copyMap, 64 | Content = dataContents 65 | }; 66 | 67 | Data.Add(dataItem); 68 | 69 | Log.Information($"Read {copyMap.Flags.Count} navigations"); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/NodesDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using UnturnedMapMergeTool.Abstractions; 7 | using UnturnedMapMergeTool.Models; 8 | using UnturnedMapMergeTool.Models.Contents; 9 | using UnturnedMapMergeTool.Models.Contents.Nodes; 10 | using UnturnedMapMergeTool.Services; 11 | 12 | namespace UnturnedMapMergeTool.DataMergeTools 13 | { 14 | public class NodesDataMergeTool : DataMergeToolBase 15 | { 16 | private List> Data { get; set; } = new(); 17 | 18 | public override void CombineAndSaveData(OutputMap outputMap) 19 | { 20 | byte saveDataVersion = 8; 21 | int count = Data.Sum(x => x.Content.Nodes.Count); 22 | byte countByte = (byte)count; 23 | 24 | NodesDataContent content = new(saveDataVersion, countByte); 25 | 26 | foreach (CopyMapData dataItem in Data) 27 | { 28 | foreach (NodeData node in dataItem.Content.Nodes) 29 | { 30 | if (dataItem.CopyMap.Config.IgnoreAirdropNodes && node.Type == 5) 31 | { 32 | continue; 33 | } 34 | 35 | if (dataItem.CopyMap.Config.IgnoreArenaNodes && node.Type == 3) 36 | { 37 | continue; 38 | } 39 | 40 | if (dataItem.CopyMap.IsOriginalPositionBypassed(node.Point)) 41 | { 42 | continue; 43 | } 44 | 45 | dataItem.CopyMap.ApplyPositionShift(node.Point); 46 | 47 | if (dataItem.CopyMap.IsOutputMapBorder(node.Point)) 48 | { 49 | continue; 50 | } 51 | 52 | content.Nodes.Add(node); 53 | } 54 | } 55 | 56 | content.Count = (byte)content.Nodes.Count; 57 | content.Nodes = content.Nodes.ToList(); 58 | 59 | // DEBUG 60 | File.WriteAllText($"nodes_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 61 | 62 | string nodesSavePath = outputMap.CombinePath("Environment/Nodes.dat"); 63 | 64 | content.SaveToFile(nodesSavePath); 65 | 66 | Log.Information($"Combined and saved {content.Nodes.Count} nodes"); 67 | } 68 | 69 | public override void ReadData(CopyMap copyMap) 70 | { 71 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Environment/Nodes.dat"); 72 | NodesDataContent content = NodesDataContent.FromFile(fileNamePath); 73 | 74 | // Write to JSON file for debug 75 | File.WriteAllText($"nodes_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 76 | 77 | CopyMapData dataItem = new() 78 | { 79 | CopyMap = copyMap, 80 | Content = content 81 | }; 82 | 83 | Data.Add(dataItem); 84 | 85 | Log.Information($"Read {content.Nodes.Count} nodes"); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/ObjectsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using UnturnedMapMergeTool.Abstractions; 7 | using UnturnedMapMergeTool.Models; 8 | using UnturnedMapMergeTool.Models.Contents; 9 | using UnturnedMapMergeTool.Models.Contents.Objects; 10 | using UnturnedMapMergeTool.Models.Contents.Trees; 11 | using UnturnedMapMergeTool.Services; 12 | using UnturnedMapMergeTool.Unturned; 13 | using UnturnedMapMergeTool.Unturned.Unity; 14 | 15 | namespace UnturnedMapMergeTool.DataMergeTools 16 | { 17 | public class ObjectsDataMergeTool : DataMergeToolBase 18 | { 19 | public List> Items { get; set; } = new List>(); 20 | 21 | public override void CombineAndSaveData(OutputMap outputMap) 22 | { 23 | uint availableInstanceId = 0; 24 | byte saveDataVersion = 12; 25 | CSteamID steamID = null; 26 | ObjectDataContent content = new(saveDataVersion, steamID, availableInstanceId); 27 | 28 | foreach (CopyMapData dataItem in Items) 29 | { 30 | List copyMapObjects = dataItem.Content.ObjectRegions.SelectMany(x => x.Objects).ToList(); 31 | 32 | foreach (ObjectData objectData in copyMapObjects) 33 | { 34 | if (!dataItem.CopyMap.ShouldIncludePosition(objectData.Position)) 35 | { 36 | Log.Warning($"OBJECT: Skipping object outside of the border"); 37 | continue; 38 | } 39 | 40 | if (dataItem.CopyMap.IsOriginalPositionBypassed(objectData.Position)) 41 | { 42 | continue; 43 | } 44 | 45 | ObjectData shiftedObjectData = new() 46 | { 47 | Position = objectData.Position, 48 | LocalScale = objectData.LocalScale, 49 | AssetId = objectData.AssetId, 50 | Guid = objectData.Guid, 51 | PlacementOrigin = objectData.PlacementOrigin, 52 | Rotation = objectData.Rotation, 53 | InstanceId = 0 54 | }; 55 | 56 | dataItem.CopyMap.ApplyPositionShift(shiftedObjectData.Position); 57 | 58 | if (!Regions.tryGetCoordinate(shiftedObjectData.Position, out byte regionX, out byte regionY)) 59 | { 60 | //Log.Warning($"OBJECT: Failed to get coordinates for {shiftedObjectData.Position}"); 61 | continue; 62 | } 63 | 64 | shiftedObjectData.InstanceId = availableInstanceId++; 65 | 66 | ObjectRegionData objectRegionData = content.ObjectRegions.First(x => x.RegionX == regionX && x.RegionY == regionY); 67 | 68 | objectRegionData.Objects.Add(shiftedObjectData); 69 | objectRegionData.Count++; 70 | } 71 | } 72 | 73 | string objectsSavePath = outputMap.CombinePath("Level/Objects.dat"); 74 | 75 | content.SaveToFile(objectsSavePath); 76 | 77 | Log.Information($"Combined and saved {content.ObjectRegions.Sum(x => x.Count)} objects"); 78 | } 79 | 80 | public override void ReadData(CopyMap copyMap) 81 | { 82 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Level/Objects.dat"); 83 | ObjectDataContent content = ObjectDataContent.FromFile(fileNamePath); 84 | 85 | // Write to JSON file for debug 86 | File.WriteAllText($"objects_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 87 | 88 | int objectsCount = content.ObjectRegions.Sum(x => x.Count); 89 | 90 | CopyMapData dataItem = new() 91 | { 92 | CopyMap = copyMap, 93 | Content = content 94 | }; 95 | 96 | Items.Add(dataItem); 97 | 98 | Log.Information($"Read {objectsCount} objects"); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/PathsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using UnturnedMapMergeTool.Abstractions; 8 | using UnturnedMapMergeTool.Models; 9 | using UnturnedMapMergeTool.Models.Contents; 10 | using UnturnedMapMergeTool.Models.Contents.Objects; 11 | using UnturnedMapMergeTool.Models.Contents.Paths; 12 | using UnturnedMapMergeTool.Models.Contents.Trees; 13 | using UnturnedMapMergeTool.Services; 14 | using UnturnedMapMergeTool.Unturned; 15 | 16 | namespace UnturnedMapMergeTool.DataMergeTools 17 | { 18 | public class PathsDataMergeTool : DataMergeToolBase 19 | { 20 | private List> Data { get; set; } = new(); 21 | 22 | public override void CombineAndSaveData(OutputMap outputMap) 23 | { 24 | byte saveDataVersion = 5; 25 | ushort count = (ushort)Data.Sum(x => x.Content.PathLines.Count); 26 | PathsDataContent content = new(saveDataVersion, count); 27 | 28 | foreach (CopyMapData dataItem in Data) 29 | { 30 | foreach (PathLineData pathLine in dataItem.Content.PathLines) 31 | { 32 | PathLineData shiftedPathLine = new() 33 | { 34 | Material = pathLine.Material, 35 | Joints = new(), 36 | NewLoop = pathLine.NewLoop 37 | }; 38 | 39 | //pathLine.Material = dataItem.CopyMap.ApplyMaterialShift(pathLine.Material); 40 | foreach (PathJointData pathJoint in pathLine.Joints) 41 | { 42 | PathJointData shiftedPathJoint = new() 43 | { 44 | Tangents = pathJoint.Tangents, 45 | IgnoreTerrain = pathJoint.IgnoreTerrain, 46 | Offset = pathJoint.Offset, 47 | RoadMode = pathJoint.RoadMode, 48 | Vertex = pathJoint.Vertex 49 | }; 50 | 51 | if (dataItem.CopyMap.IsOriginalPositionBypassed(pathJoint.Vertex)) 52 | { 53 | continue; 54 | } 55 | 56 | dataItem.CopyMap.ApplyPositionShift(shiftedPathJoint.Vertex); 57 | shiftedPathLine.Joints.Add(shiftedPathJoint); 58 | } 59 | 60 | 61 | shiftedPathLine.Count = (ushort)shiftedPathLine.Joints.Count; 62 | 63 | if (shiftedPathLine.Count > 0) 64 | { 65 | content.PathLines.Add(shiftedPathLine); 66 | } 67 | } 68 | 69 | content.Count = (ushort)content.PathLines.Count; 70 | } 71 | 72 | string pathsSavePath = outputMap.CombinePath("Environment/Paths.dat"); 73 | 74 | content.SaveToFile(pathsSavePath); 75 | 76 | Log.Information($"Combined and saved {content.PathLines.Count} path lines and {content.PathLines.Sum(x => x.Count)} path joints"); 77 | } 78 | 79 | public override void ReadData(CopyMap copyMap) 80 | { 81 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Environment/Paths.dat"); 82 | PathsDataContent content = PathsDataContent.FromFile(fileNamePath); 83 | 84 | // Write to JSON file for debug 85 | File.WriteAllText($"paths_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 86 | 87 | int pathLinesCount = content.PathLines.Count; 88 | int pathJoinsCount = content.PathLines.Sum(x => x.Count); 89 | 90 | CopyMapData dataItem = new() 91 | { 92 | CopyMap = copyMap, 93 | Content = content 94 | }; 95 | 96 | Data.Add(dataItem); 97 | 98 | Log.Information($"Read {pathLinesCount} path lines and {pathJoinsCount} path joins"); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/RoadsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using UnturnedMapMergeTool.Abstractions; 7 | using UnturnedMapMergeTool.Models; 8 | using UnturnedMapMergeTool.Models.Contents; 9 | using UnturnedMapMergeTool.Models.Contents.Roads; 10 | using UnturnedMapMergeTool.Services; 11 | 12 | namespace UnturnedMapMergeTool.DataMergeTools 13 | { 14 | public class RoadsDataMergeTool : DataMergeToolBase 15 | { 16 | public List> Data { get; set; } = new(); 17 | 18 | public override void CombineAndSaveData(OutputMap outputMap) 19 | { 20 | byte saveDataVersion = 2; 21 | byte count = (byte)Data.Sum(x => x.Content.Materials.Count); 22 | RoadsDataContent content = new(saveDataVersion, count); 23 | 24 | byte materialId = 0; 25 | foreach (CopyMapData dataItem in Data) 26 | { 27 | dataItem.CopyMap.MaterialShift = materialId; 28 | foreach (RoadMaterialData roadMaterial in dataItem.Content.Materials) 29 | { 30 | content.Materials.Add(roadMaterial); 31 | materialId++; 32 | } 33 | } 34 | 35 | string roadsSavePath = outputMap.CombinePath("Environment/Roads.dat"); 36 | 37 | content.SaveToFile(roadsSavePath); 38 | 39 | Log.Information($"Combined and saved {content.Materials.Count} road materials"); 40 | } 41 | 42 | public override void ReadData(CopyMap copyMap) 43 | { 44 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Environment/Roads.dat"); 45 | RoadsDataContent content = RoadsDataContent.FromFile(fileNamePath); 46 | 47 | // Write to JSON file for debug 48 | File.WriteAllText($"roads_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 49 | 50 | CopyMapData dataItem = new() 51 | { 52 | CopyMap = copyMap, 53 | Content = content 54 | }; 55 | 56 | Data.Add(dataItem); 57 | 58 | Log.Information($"Read {content.Count} road materials"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/Spawns/AnimalsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using UnturnedMapMergeTool.Abstractions; 10 | using UnturnedMapMergeTool.Models.Contents; 11 | using UnturnedMapMergeTool.Models; 12 | using UnturnedMapMergeTool.Services; 13 | using UnturnedMapMergeTool.Models.Contents.Zombies; 14 | using UnturnedMapMergeTool.Models.Contents.Animals; 15 | using UnturnedMapMergeTool.Models.Contents.Trees; 16 | using UnturnedMapMergeTool.Unturned; 17 | using UnturnedMapMergeTool.Models.Contents.Objects; 18 | 19 | namespace UnturnedMapMergeTool.DataMergeTools.Spawns 20 | { 21 | public class AnimalsDataMergeTool : DataMergeToolBase 22 | { 23 | private List> Data { get; set; } = new(); 24 | 25 | public override void CombineAndSaveData(OutputMap outputMap) 26 | { 27 | byte saveDataVersion = 1; 28 | 29 | AnimalsDataContent content = new(saveDataVersion); 30 | 31 | foreach (CopyMapData dataItem in Data) 32 | { 33 | IEnumerable zombieSpawnpoints = dataItem.Content.ZombieRegions.SelectMany(x => x.ZombieSpawnpoints); 34 | 35 | foreach (ZombieSpawnpointData zombieSpawnpoint in zombieSpawnpoints) 36 | { 37 | if (dataItem.CopyMap.IsOriginalPositionBypassed(zombieSpawnpoint.Point)) 38 | { 39 | continue; 40 | } 41 | 42 | ZombieSpawnpointData shiftedZombieSpawnpoint = new() 43 | { 44 | Point = zombieSpawnpoint.Point, 45 | Type = zombieSpawnpoint.Type 46 | }; 47 | 48 | dataItem.CopyMap.ApplyPositionShift(shiftedZombieSpawnpoint.Point); 49 | 50 | if (dataItem.CopyMap.IsOutputMapBorder(shiftedZombieSpawnpoint.Point)) 51 | { 52 | continue; 53 | } 54 | 55 | shiftedZombieSpawnpoint.Type = dataItem.CopyMap.GetShiftedZombieType(shiftedZombieSpawnpoint.Type); 56 | 57 | if (!Regions.tryGetCoordinate(shiftedZombieSpawnpoint.Point, out byte regionX, out byte regionY)) 58 | { 59 | Log.Warning($"Zombie SpawnPoint: Failed to get coordinates for {shiftedZombieSpawnpoint.Point}"); 60 | continue; 61 | } 62 | 63 | ZombieRegionData zombieRegionData = content.ZombieRegions.First(x => x.RegionX == regionX && x.RegionY == regionY); 64 | zombieRegionData.ZombieSpawnpoints.Add(shiftedZombieSpawnpoint); 65 | zombieRegionData.Count++; 66 | } 67 | } 68 | 69 | string savePath = outputMap.CombinePath("Spawns/Animals.dat"); 70 | 71 | content.SaveToFile(savePath); 72 | 73 | // DEBUG 74 | File.WriteAllText($"animals_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 75 | 76 | Log.Information($"Combined and saved {content.ZombieRegions.Sum(x => x.Count)} zombie spawnpoints"); 77 | } 78 | 79 | public override void ReadData(CopyMap copyMap) 80 | { 81 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Spawns/Animals.dat"); 82 | AnimalsDataContent content = AnimalsDataContent.FromFile(fileNamePath); 83 | 84 | // Write to JSON file for debug 85 | File.WriteAllText($"animals_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 86 | 87 | 88 | CopyMapData dataItem = new() 89 | { 90 | CopyMap = copyMap, 91 | Content = content 92 | }; 93 | 94 | Data.Add(dataItem); 95 | 96 | Log.Information($"Read {content.ZombieRegions.Sum(x => x.Count)} zombie spawnpoints"); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/Spawns/FaunaDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using UnturnedMapMergeTool.Abstractions; 7 | using UnturnedMapMergeTool.Models; 8 | using UnturnedMapMergeTool.Models.Contents; 9 | using UnturnedMapMergeTool.Models.Contents.Faunas; 10 | using UnturnedMapMergeTool.Services; 11 | 12 | namespace UnturnedMapMergeTool.DataMergeTools.Spawns 13 | { 14 | public class FaunaDataMergeTool : DataMergeToolBase 15 | { 16 | private List> Data { get; set; } = new(); 17 | 18 | public override void CombineAndSaveData(OutputMap outputMap) 19 | { 20 | byte saveDataVersion = 3; 21 | byte tablesCount = (byte)Data.Sum(x => x.Content.TablesCount); 22 | ushort spawnpointsCount = (ushort)Data.Sum(x => x.Content.SpawnPointsCount); 23 | 24 | FaunaDataContent content = new(saveDataVersion, tablesCount, spawnpointsCount); 25 | 26 | byte tableId = 0; 27 | foreach (CopyMapData dataItem in Data) 28 | { 29 | byte startTableId = tableId; 30 | 31 | foreach (AnimalTableData animalTable in dataItem.Content.Tables) 32 | { 33 | content.Tables.Add(animalTable); 34 | tableId++; 35 | } 36 | 37 | foreach (AnimalSpawnpointData animalSpawnPoint in dataItem.Content.SpawnPoints) 38 | { 39 | if (dataItem.CopyMap.IsOriginalPositionBypassed(animalSpawnPoint.Point)) 40 | { 41 | continue; 42 | } 43 | 44 | animalSpawnPoint.Type = (byte)(animalSpawnPoint.Type + startTableId); 45 | dataItem.CopyMap.ApplyPositionShift(animalSpawnPoint.Point); 46 | 47 | if (dataItem.CopyMap.IsOutputMapBorder(animalSpawnPoint.Point)) 48 | { 49 | continue; 50 | } 51 | 52 | content.SpawnPoints.Add(animalSpawnPoint); 53 | } 54 | } 55 | 56 | string savePath = outputMap.CombinePath("Spawns/Fauna.dat"); 57 | 58 | content.SaveToFile(savePath); 59 | 60 | // DEBUG 61 | File.WriteAllText($"fauna_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 62 | 63 | Log.Information($"Combined and saved {content.TablesCount} fauna tables and {content.SpawnPointsCount} spawnpoints"); 64 | } 65 | 66 | public override void ReadData(CopyMap copyMap) 67 | { 68 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Spawns/Fauna.dat"); 69 | FaunaDataContent content = FaunaDataContent.FromFile(fileNamePath); 70 | 71 | // Write to JSON file for debug 72 | File.WriteAllText($"fauna_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 73 | 74 | 75 | CopyMapData dataItem = new() 76 | { 77 | CopyMap = copyMap, 78 | Content = content 79 | }; 80 | 81 | Data.Add(dataItem); 82 | 83 | Log.Information($"Read {content.TablesCount} fauna tables and {content.SpawnPointsCount} spawnpoints"); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/Spawns/ItemsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using UnturnedMapMergeTool.Abstractions; 10 | using UnturnedMapMergeTool.Models; 11 | using UnturnedMapMergeTool.Models.Contents; 12 | using UnturnedMapMergeTool.Models.Contents.Items; 13 | using UnturnedMapMergeTool.Models.Contents.Vehicles; 14 | using UnturnedMapMergeTool.Services; 15 | 16 | namespace UnturnedMapMergeTool.DataMergeTools.Spawns 17 | { 18 | public class ItemsDataMergeTool : DataMergeToolBase 19 | { 20 | private List> Data { get; set; } = new(); 21 | 22 | public override void CombineAndSaveData(OutputMap outputMap) 23 | { 24 | byte saveDataVersion = 4; 25 | byte tablesCount = (byte)Data.Sum(x => x.Content.TablesCount); 26 | 27 | ItemsDataContent content = new(saveDataVersion, tablesCount); 28 | 29 | byte tableId = 0; 30 | foreach (CopyMapData dataItem in Data) 31 | { 32 | dataItem.CopyMap.ItemTypeShift = tableId; 33 | 34 | foreach (ItemTableData vehicleTable in dataItem.Content.Tables) 35 | { 36 | content.Tables.Add(vehicleTable); 37 | tableId++; 38 | } 39 | } 40 | 41 | string savePath = outputMap.CombinePath("Spawns/Items.dat"); 42 | 43 | content.SaveToFile(savePath); 44 | 45 | // DEBUG 46 | File.WriteAllText($"items_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 47 | 48 | Log.Information($"Combined and saved {content.TablesCount} item tables"); 49 | } 50 | 51 | public override void ReadData(CopyMap copyMap) 52 | { 53 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Spawns/Items.dat"); 54 | ItemsDataContent content = ItemsDataContent.FromFile(fileNamePath); 55 | 56 | // Write to JSON file for debug 57 | File.WriteAllText($"items_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 58 | 59 | CopyMapData dataItem = new() 60 | { 61 | CopyMap = copyMap, 62 | Content = content 63 | }; 64 | 65 | Data.Add(dataItem); 66 | 67 | Log.Information($"Read {content.TablesCount} item tables"); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/Spawns/JarsDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using UnturnedMapMergeTool.Abstractions; 7 | using UnturnedMapMergeTool.Models; 8 | using UnturnedMapMergeTool.Models.Contents; 9 | using UnturnedMapMergeTool.Models.Contents.Jars; 10 | using UnturnedMapMergeTool.Services; 11 | using UnturnedMapMergeTool.Unturned; 12 | 13 | namespace UnturnedMapMergeTool.DataMergeTools.Spawns 14 | { 15 | public class JarsDataMergeTool : DataMergeToolBase 16 | { 17 | private List> Data { get; set; } = new(); 18 | 19 | public override void CombineAndSaveData(OutputMap outputMap) 20 | { 21 | byte saveDataVersion = 1; 22 | 23 | JarsDataContent content = new(saveDataVersion); 24 | 25 | foreach (CopyMapData dataItem in Data) 26 | { 27 | IEnumerable itemSpawnpoints = dataItem.Content.ItemRegions.SelectMany(x => x.Spawnpoints); 28 | 29 | foreach (ItemSpawnpointData itemSpawnpoint in itemSpawnpoints) 30 | { 31 | if (dataItem.CopyMap.IsOriginalPositionBypassed(itemSpawnpoint.Point)) 32 | { 33 | continue; 34 | } 35 | 36 | ItemSpawnpointData shiftedItemSpawnpoint = new() 37 | { 38 | Point = itemSpawnpoint.Point, 39 | Type = itemSpawnpoint.Type 40 | }; 41 | 42 | dataItem.CopyMap.ApplyPositionShift(shiftedItemSpawnpoint.Point); 43 | 44 | if (dataItem.CopyMap.IsOutputMapBorder(shiftedItemSpawnpoint.Point)) 45 | { 46 | continue; 47 | } 48 | 49 | shiftedItemSpawnpoint.Type = dataItem.CopyMap.GetShiftedItemType(shiftedItemSpawnpoint.Type); 50 | 51 | if (!Regions.tryGetCoordinate(shiftedItemSpawnpoint.Point, out byte regionX, out byte regionY)) 52 | { 53 | Log.Warning($"Item SpawnPoint: Failed to get coordinates for {shiftedItemSpawnpoint.Point}"); 54 | continue; 55 | } 56 | 57 | ItemRegionData itemRegionData = content.ItemRegions.First(x => x.RegionX == regionX && x.RegionY == regionY); 58 | itemRegionData.Spawnpoints.Add(shiftedItemSpawnpoint); 59 | itemRegionData.SpawnpointsCount++; 60 | } 61 | } 62 | 63 | string savePath = outputMap.CombinePath("Spawns/Jars.dat"); 64 | 65 | content.SaveToFile(savePath); 66 | 67 | // DEBUG 68 | File.WriteAllText($"jars_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 69 | 70 | Log.Information($"Combined and saved {content.ItemRegions.Sum(x => x.SpawnpointsCount)} item spawnpoints"); 71 | } 72 | 73 | public override void ReadData(CopyMap copyMap) 74 | { 75 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Spawns/Jars.dat"); 76 | JarsDataContent content = JarsDataContent.FromFile(fileNamePath); 77 | 78 | // Write to JSON file for debug 79 | File.WriteAllText($"jars_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 80 | 81 | 82 | CopyMapData dataItem = new() 83 | { 84 | CopyMap = copyMap, 85 | Content = content 86 | }; 87 | 88 | Data.Add(dataItem); 89 | 90 | Log.Information($"Read {content.ItemRegions.Sum(x => x.SpawnpointsCount)} item spawnpoints"); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/Spawns/PlayersDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using UnturnedMapMergeTool.Abstractions; 8 | using UnturnedMapMergeTool.Models; 9 | using UnturnedMapMergeTool.Models.Contents; 10 | using UnturnedMapMergeTool.Models.Contents.Players; 11 | using UnturnedMapMergeTool.Models.Contents.Zombies; 12 | using UnturnedMapMergeTool.Services; 13 | 14 | namespace UnturnedMapMergeTool.DataMergeTools.Spawns 15 | { 16 | public class PlayersDataMergeTool : DataMergeToolBase 17 | { 18 | private List> Data { get; set; } = new(); 19 | 20 | public override void CombineAndSaveData(OutputMap outputMap) 21 | { 22 | byte saveDataVersion = 4; 23 | byte count = (byte)Data.Sum(x => x.Content.Spawns.Count); 24 | 25 | PlayersDataContent content = new(saveDataVersion, count); 26 | 27 | foreach (CopyMapData dataItem in Data) 28 | { 29 | foreach (PlayerSpawnData playerSpawn in dataItem.Content.Spawns) 30 | { 31 | if (dataItem.CopyMap.IsOriginalPositionBypassed(playerSpawn.Point)) 32 | { 33 | continue; 34 | } 35 | 36 | dataItem.CopyMap.ApplyPositionShift(playerSpawn.Point); 37 | 38 | if (dataItem.CopyMap.IsOutputMapBorder(playerSpawn.Point)) 39 | { 40 | continue; 41 | } 42 | 43 | content.Spawns.Add(playerSpawn); 44 | } 45 | } 46 | 47 | string savePath = outputMap.CombinePath("Spawns/Players.dat"); 48 | 49 | content.SaveToFile(savePath); 50 | 51 | // DEBUG 52 | File.WriteAllText($"players_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 53 | 54 | Log.Information($"Combined and saved {content.Count} players spawns"); 55 | } 56 | 57 | public override void ReadData(CopyMap copyMap) 58 | { 59 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Spawns/Players.dat"); 60 | PlayersDataContent content = PlayersDataContent.FromFile(fileNamePath); 61 | 62 | // Write to JSON file for debug 63 | File.WriteAllText($"players_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 64 | 65 | 66 | CopyMapData dataItem = new() 67 | { 68 | CopyMap = copyMap, 69 | Content = content 70 | }; 71 | 72 | Data.Add(dataItem); 73 | 74 | Log.Information($"Read {content.Spawns.Count} player spawns"); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/Spawns/VehiclesDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using UnturnedMapMergeTool.Abstractions; 8 | using UnturnedMapMergeTool.Models; 9 | using UnturnedMapMergeTool.Models.Contents; 10 | using UnturnedMapMergeTool.Models.Contents.Faunas; 11 | using UnturnedMapMergeTool.Models.Contents.Vehicles; 12 | using UnturnedMapMergeTool.Services; 13 | 14 | namespace UnturnedMapMergeTool.DataMergeTools.Spawns 15 | { 16 | public class VehiclesDataMergeTool : DataMergeToolBase 17 | { 18 | private List> Data { get; set; } = new(); 19 | 20 | public override void CombineAndSaveData(OutputMap outputMap) 21 | { 22 | byte saveDataVersion = 4; 23 | byte tablesCount = (byte)Data.Sum(x => x.Content.TablesCount); 24 | ushort spawnpointsCount = (ushort)Data.Sum(x => x.Content.SpawnpointsCount); 25 | 26 | VehiclesDataContent content = new(saveDataVersion, tablesCount, spawnpointsCount); 27 | 28 | byte tableId = 0; 29 | foreach (CopyMapData dataItem in Data) 30 | { 31 | byte startTableId = tableId; 32 | 33 | foreach (VehicleTableData vehicleTable in dataItem.Content.Tables) 34 | { 35 | content.Tables.Add(vehicleTable); 36 | tableId++; 37 | } 38 | 39 | foreach (VehicleSpawnpointData vehicleSpawnpoint in dataItem.Content.Spawnpoints) 40 | { 41 | if (dataItem.CopyMap.IsOriginalPositionBypassed(vehicleSpawnpoint.Point)) 42 | { 43 | continue; 44 | } 45 | 46 | vehicleSpawnpoint.Type = (byte)(vehicleSpawnpoint.Type + startTableId); 47 | dataItem.CopyMap.ApplyPositionShift(vehicleSpawnpoint.Point); 48 | 49 | if (dataItem.CopyMap.IsOutputMapBorder(vehicleSpawnpoint.Point)) 50 | { 51 | continue; 52 | } 53 | 54 | content.Spawnpoints.Add(vehicleSpawnpoint); 55 | } 56 | } 57 | 58 | string savePath = outputMap.CombinePath("Spawns/Vehicles.dat"); 59 | 60 | content.SaveToFile(savePath); 61 | 62 | // DEBUG 63 | File.WriteAllText($"vehicles_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 64 | 65 | Log.Information($"Combined and saved {content.TablesCount} vehicle tables and {content.SpawnpointsCount} spawnpoints"); 66 | } 67 | 68 | public override void ReadData(CopyMap copyMap) 69 | { 70 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Spawns/Vehicles.dat"); 71 | VehiclesDataContent content = VehiclesDataContent.FromFile(fileNamePath); 72 | 73 | // Write to JSON file for debug 74 | File.WriteAllText($"vehicles_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 75 | 76 | CopyMapData dataItem = new() 77 | { 78 | CopyMap = copyMap, 79 | Content = content 80 | }; 81 | 82 | Data.Add(dataItem); 83 | 84 | Log.Information($"Read {content.TablesCount} vehicle tables and {content.SpawnpointsCount} spawnpoints"); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/Spawns/ZombiesDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using UnturnedMapMergeTool.Abstractions; 8 | using UnturnedMapMergeTool.Models; 9 | using UnturnedMapMergeTool.Models.Contents; 10 | using UnturnedMapMergeTool.Models.Contents.Bounds; 11 | using UnturnedMapMergeTool.Models.Contents.Flags; 12 | using UnturnedMapMergeTool.Models.Contents.Zombies; 13 | using UnturnedMapMergeTool.Services; 14 | 15 | namespace UnturnedMapMergeTool.DataMergeTools.Spawns 16 | { 17 | public class ZombiesDataMergeTool : DataMergeToolBase 18 | { 19 | private List> Data { get; set; } = new(); 20 | 21 | public override void CombineAndSaveData(OutputMap outputMap) 22 | { 23 | byte saveDataVersion = 9; 24 | byte count = (byte)Data.Sum(x => x.Content.Tables.Count); 25 | 26 | ZombiesDataContent content = new(saveDataVersion, count); 27 | 28 | byte zombieType = 0; 29 | foreach (CopyMapData dataItem in Data) 30 | { 31 | dataItem.CopyMap.ZombieTypeShift = zombieType; 32 | 33 | foreach (ZombieTableData zombieTable in dataItem.Content.Tables) 34 | { 35 | content.Tables.Add(zombieTable); 36 | zombieType++; 37 | } 38 | } 39 | 40 | string savePath = outputMap.CombinePath("Spawns/Zombies.dat"); 41 | 42 | content.SaveToFile(savePath); 43 | 44 | // DEBUG 45 | File.WriteAllText($"zombies_output.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 46 | 47 | Log.Information($"Combined and saved {content.Tables.Count} zombie tables"); 48 | } 49 | 50 | public override void ReadData(CopyMap copyMap) 51 | { 52 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Spawns/Zombies.dat"); 53 | ZombiesDataContent content = ZombiesDataContent.FromFile(fileNamePath); 54 | 55 | // Write to JSON file for debug 56 | File.WriteAllText($"zombies_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 57 | 58 | 59 | CopyMapData dataItem = new() 60 | { 61 | CopyMap = copyMap, 62 | Content = content 63 | }; 64 | 65 | Data.Add(dataItem); 66 | 67 | Log.Information($"Read {content.Tables.Count} zombie tables"); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/DataMergeTools/TreesDataMergeTool.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using UnturnedMapMergeTool.Abstractions; 7 | using UnturnedMapMergeTool.Models; 8 | using UnturnedMapMergeTool.Models.Contents; 9 | using UnturnedMapMergeTool.Models.Contents.Trees; 10 | using UnturnedMapMergeTool.Services; 11 | using UnturnedMapMergeTool.Unturned; 12 | 13 | namespace UnturnedMapMergeTool.DataMergeTools 14 | { 15 | public class TreesDataMergeTool : DataMergeToolBase 16 | { 17 | private List> Data { get; set; } = new List>(); 18 | 19 | public override void CombineAndSaveData(OutputMap outputMap) 20 | { 21 | byte saveDataVersion = 6; 22 | TreesDataContent content = new(saveDataVersion); 23 | 24 | foreach (CopyMapData dataItem in Data) 25 | { 26 | IEnumerable copyMapBuildables = dataItem.Content.TreeRegions.SelectMany(x => x.Trees); 27 | 28 | foreach (TreeData treeData in copyMapBuildables) 29 | { 30 | if (dataItem.CopyMap.IsOriginalPositionBypassed(treeData.Position)) 31 | { 32 | continue; 33 | } 34 | 35 | TreeData shiftedTreeData = new() 36 | { 37 | Position = treeData.Position, 38 | Guid = treeData.Guid, 39 | AssetId = treeData.AssetId, 40 | IsGenerated = treeData.IsGenerated 41 | }; 42 | 43 | dataItem.CopyMap.ApplyPositionShift(shiftedTreeData.Position); 44 | 45 | if (!Regions.tryGetCoordinate(shiftedTreeData.Position, out byte regionX, out byte regionY)) 46 | { 47 | //Log.Warning($"TREE: Failed to get coordinates for {shiftedTreeData.Position}"); 48 | continue; 49 | } 50 | 51 | TreeRegionData treeRegionData = content.TreeRegions.First(x => x.RegionX == regionX && x.RegionY == regionY); 52 | treeRegionData.Trees.Add(shiftedTreeData); 53 | treeRegionData.Count++; 54 | } 55 | } 56 | 57 | string treesSavePath = outputMap.CombinePath("Terrain/Trees.dat"); 58 | 59 | content.SaveToFile(treesSavePath); 60 | 61 | Log.Information($"Combined and saved {content.TreeRegions.Sum(x => x.Count)} trees"); 62 | } 63 | 64 | public override void ReadData(CopyMap copyMap) 65 | { 66 | string fileNamePath = Path.Combine(copyMap.Config.Path, "Terrain/Trees.dat"); 67 | TreesDataContent content = TreesDataContent.FromFile(fileNamePath); 68 | 69 | // Write to json file for debug 70 | File.WriteAllText($"trees_{copyMap.Config.Name}.json", JsonConvert.SerializeObject(content, Formatting.Indented)); 71 | 72 | CopyMapData dataItem = new() 73 | { 74 | CopyMap = copyMap, 75 | Content = content 76 | }; 77 | 78 | Data.Add(dataItem); 79 | 80 | int treesCount = content.TreeRegions.Sum(x => x.Count); 81 | Log.Information($"Read {treesCount} trees"); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Extensions 2 | { 3 | public static class StringExtensions 4 | { 5 | public static string TrimEnd(this string source, string value) 6 | { 7 | if (!source.EndsWith(value)) 8 | return source; 9 | 10 | return source.Remove(source.LastIndexOf(value)); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Helpers/TilesHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnturnedMapMergeTool.Models.Enums; 5 | using UnturnedMapMergeTool.Unturned.Unity; 6 | 7 | namespace UnturnedMapMergeTool.Helpers 8 | { 9 | public class TilesHelper 10 | { 11 | private static Dictionary MapTiles = new() 12 | { 13 | { EMapSize.Tiny, new int[] { -1, 0 } }, 14 | { EMapSize.Small, new int[] { -1, 0 } }, 15 | { EMapSize.Medium, new int[] { -1, 0 } }, 16 | { EMapSize.Large, new int[] { -2, -1, 0, 1 } }, 17 | { EMapSize.Insane, new int[] { -4, -3, -2, -1, 0, 1, 2, 3 } } 18 | }; 19 | 20 | public static int TileToIndex(int tile, EMapSize mapSize) 21 | { 22 | return mapSize switch 23 | { 24 | EMapSize.Tiny => tile + 1, 25 | EMapSize.Small => tile + 1, 26 | EMapSize.Medium => tile + 1, 27 | EMapSize.Large => tile + 2, 28 | EMapSize.Insane => tile + 4, 29 | _ => throw new NotSupportedException($"{mapSize} map size is not supported") 30 | }; 31 | } 32 | 33 | public static int IndexToTile(int index, EMapSize mapSize) 34 | { 35 | return mapSize switch 36 | { 37 | EMapSize.Tiny => index - 1, 38 | EMapSize.Small => index - 1, 39 | EMapSize.Medium => index - 1, 40 | EMapSize.Large => index - 2, 41 | EMapSize.Insane => index - 4, 42 | _ => throw new NotSupportedException($"{mapSize} map size not supported") 43 | }; 44 | } 45 | 46 | public static int TileToShift(int tile, EMapSize mapSize) 47 | { 48 | return mapSize switch 49 | { 50 | EMapSize.Tiny => tile - 1, 51 | EMapSize.Small => tile - 1, 52 | EMapSize.Medium => tile - 1, 53 | EMapSize.Large => tile - 2, 54 | EMapSize.Insane => tile - 4, 55 | _ => throw new NotSupportedException($"{mapSize} map size not supported") 56 | }; 57 | } 58 | 59 | public static bool IsBorder(int tileX, int tileY, EMapSize mapSize) 60 | { 61 | if (!MapTiles[mapSize].Contains(tileX)) 62 | { 63 | return true; 64 | } 65 | 66 | if (!MapTiles[mapSize].Contains(tileY)) 67 | { 68 | return true; 69 | } 70 | 71 | return false; 72 | } 73 | 74 | public static bool IsBorder(Vector3 position, EMapSize mapSize) 75 | { 76 | int min = MapTiles[mapSize].Min() * 1024; 77 | int max = (MapTiles[mapSize].Max() + 1) * 1024; 78 | 79 | if (position.z > max || position.z < min) 80 | return true; 81 | if (position.x > max || position.x < min) 82 | return true; 83 | 84 | return false; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Configs/CopyMapConfig.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Models.Enums; 2 | 3 | namespace UnturnedMapMergeTool.Models.Configs 4 | { 5 | public class CopyMapConfig 6 | { 7 | public string Name { get; set; } 8 | public string Path { get; set; } 9 | public EMapSize Size { get; set; } 10 | public bool WithBorders { get; set; } 11 | public Coordinate StartCoordinate { get; set; } 12 | public int ShiftX { get; set; } 13 | public int ShiftY { get; set; } 14 | public bool IgnoreAirdropNodes { get; set; } 15 | public bool IgnoreArenaNodes { get; set; } 16 | public Coordinate[] BypassTiles { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Configs/OutputMapConfig.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Models.Enums; 2 | 3 | namespace UnturnedMapMergeTool.Models.Configs 4 | { 5 | public class OutputMapConfig 6 | { 7 | public string Path { get; set; } 8 | public EMapSize Size { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Animals/ZombieRegionData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Animals 4 | { 5 | public class ZombieRegionData 6 | { 7 | public byte RegionX { get; set; } 8 | public byte RegionY { get; set; } 9 | public ushort Count { get; set; } 10 | public List ZombieSpawnpoints { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Animals/ZombieSpawnpointData.cs: -------------------------------------------------------------------------------- 1 |  2 | using UnturnedMapMergeTool.Unturned.Unity; 3 | 4 | namespace UnturnedMapMergeTool.Models.Contents.Animals 5 | { 6 | public class ZombieSpawnpointData 7 | { 8 | public byte Type { get; set; } 9 | public Vector3 Point { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/AnimalsDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using UnturnedMapMergeTool.Models.Contents.Animals; 4 | using UnturnedMapMergeTool.Unturned; 5 | 6 | namespace UnturnedMapMergeTool.Models.Contents 7 | { 8 | public class AnimalsDataContent 9 | { 10 | public byte SaveDataVersion { get; set; } 11 | public List ZombieRegions { get; set; } 12 | 13 | public AnimalsDataContent() 14 | { 15 | 16 | } 17 | 18 | public AnimalsDataContent(byte saveDataVersion) 19 | { 20 | SaveDataVersion = saveDataVersion; 21 | 22 | ZombieRegions = new List(); 23 | 24 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 25 | { 26 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 27 | { 28 | ZombieRegionData zombieRegionData = new() 29 | { 30 | RegionX = i, 31 | RegionY = j, 32 | Count = 0, 33 | ZombieSpawnpoints = new List() 34 | }; 35 | 36 | ZombieRegions.Add(zombieRegionData); 37 | } 38 | } 39 | } 40 | 41 | public void SaveToFile(string fileNamePath) 42 | { 43 | River river = new(fileNamePath); 44 | river.writeByte(SaveDataVersion); 45 | 46 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 47 | { 48 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 49 | { 50 | ZombieRegionData regionData = ZombieRegions.First(x => x.RegionX == i && x.RegionY == j); 51 | river.writeUInt16(regionData.Count); 52 | 53 | foreach (ZombieSpawnpointData zombieSpawnpoint in regionData.ZombieSpawnpoints) 54 | { 55 | river.writeByte(zombieSpawnpoint.Type); 56 | river.writeSingleVector3(zombieSpawnpoint.Point); 57 | } 58 | } 59 | } 60 | 61 | river.closeRiver(); 62 | } 63 | 64 | public static AnimalsDataContent FromFile(string fileNamePath) 65 | { 66 | River river = new(fileNamePath); 67 | 68 | AnimalsDataContent content = new(); 69 | 70 | content.SaveDataVersion = river.readByte(); 71 | 72 | content.ZombieRegions = new List(); 73 | 74 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 75 | { 76 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 77 | { 78 | ZombieRegionData region = new() 79 | { 80 | RegionX = i, 81 | RegionY = j 82 | }; 83 | 84 | region.Count = river.readUInt16(); 85 | 86 | region.ZombieSpawnpoints = new List(); 87 | 88 | for (ushort k = 0; k < region.Count; k++) 89 | { 90 | ZombieSpawnpointData zombieSpawnpoint = new(); 91 | 92 | zombieSpawnpoint.Type = river.readByte(); 93 | zombieSpawnpoint.Point = river.readSingleVector3(); 94 | 95 | region.ZombieSpawnpoints.Add(zombieSpawnpoint); 96 | } 97 | 98 | content.ZombieRegions.Add(region); 99 | } 100 | } 101 | 102 | river.closeRiver(); 103 | 104 | return content; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Bounds/BoundData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnturnedMapMergeTool.Unturned.Unity; 7 | 8 | namespace UnturnedMapMergeTool.Models.Contents.Bounds 9 | { 10 | public class BoundData 11 | { 12 | public Vector3 Center { get; set; } 13 | public Vector3 Size { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/BoundsDataContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnturnedMapMergeTool.Models.Contents.Bounds; 7 | using UnturnedMapMergeTool.Unturned; 8 | 9 | namespace UnturnedMapMergeTool.Models.Contents 10 | { 11 | public class BoundsDataContent 12 | { 13 | public BoundsDataContent(byte saveDataVersion, byte count) 14 | { 15 | SaveDataVersion = saveDataVersion; 16 | Count = count; 17 | 18 | Bounds = new List(); 19 | } 20 | 21 | public BoundsDataContent() 22 | { 23 | 24 | } 25 | 26 | public byte SaveDataVersion { get; set; } 27 | public byte Count { get; set; } 28 | 29 | public List Bounds { get; set; } 30 | 31 | public void SaveToFile(string fileNamePath) 32 | { 33 | River river = new(fileNamePath); 34 | 35 | river.writeByte(SaveDataVersion); 36 | river.writeByte(Count); 37 | 38 | foreach (BoundData bound in Bounds) 39 | { 40 | river.writeSingleVector3(bound.Center); 41 | river.writeSingleVector3(bound.Size); 42 | } 43 | 44 | river.closeRiver(); 45 | } 46 | 47 | public static BoundsDataContent FromFile(string fileNamePath) 48 | { 49 | River river = new(fileNamePath); 50 | 51 | BoundsDataContent content = new(); 52 | content.Bounds = new(); 53 | 54 | content.SaveDataVersion = river.readByte(); 55 | content.Count = river.readByte(); 56 | 57 | for (int i = 0; i < content.Count; i++) 58 | { 59 | BoundData bound = new(); 60 | content.Bounds.Add(bound); 61 | 62 | bound.Center = river.readSingleVector3(); 63 | bound.Size = river.readSingleVector3(); 64 | } 65 | 66 | river.closeRiver(); 67 | return content; 68 | } 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/BuildableDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using UnturnedMapMergeTool.Models.Contents.Buildables; 4 | using UnturnedMapMergeTool.Models.Contents.Objects; 5 | using UnturnedMapMergeTool.Unturned; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents 8 | { 9 | public class BuildableDataContent 10 | { 11 | public byte SaveDataVersion { get; set; } 12 | public List BuildableRegions { get; set; } 13 | 14 | public BuildableDataContent() 15 | { 16 | 17 | } 18 | 19 | public BuildableDataContent(byte saveDataVersion) 20 | { 21 | SaveDataVersion = saveDataVersion; 22 | 23 | BuildableRegions = new List(); 24 | 25 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 26 | { 27 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 28 | { 29 | BuildableRegionData buildableRegionData = new() 30 | { 31 | RegionX = i, 32 | RegionY = j, 33 | Count = 0, 34 | Buildables = new List() 35 | }; 36 | 37 | BuildableRegions.Add(buildableRegionData); 38 | } 39 | } 40 | } 41 | 42 | public void SaveToFile(string fileNamePath) 43 | { 44 | River river = new(fileNamePath); 45 | river.writeByte(SaveDataVersion); 46 | 47 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 48 | { 49 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 50 | { 51 | BuildableRegionData regionData = BuildableRegions.First(x => x.RegionX == i && x.RegionY == j); 52 | river.writeUInt16(regionData.Count); 53 | 54 | foreach (BuildableData buildableData in regionData.Buildables) 55 | { 56 | river.writeSingleVector3(buildableData.Position); 57 | river.writeSingleQuaternion(buildableData.Rotation); 58 | river.writeUInt16(buildableData.AssetId); 59 | } 60 | } 61 | } 62 | 63 | river.closeRiver(); 64 | } 65 | 66 | public static BuildableDataContent FromFile(string fileNamePath) 67 | { 68 | River river = new(fileNamePath); 69 | 70 | BuildableDataContent content = new(); 71 | 72 | content.SaveDataVersion = river.readByte(); 73 | 74 | content.BuildableRegions = new List(); 75 | 76 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 77 | { 78 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 79 | { 80 | BuildableRegionData region = new() 81 | { 82 | RegionX = i, 83 | RegionY = j 84 | }; 85 | 86 | region.Count = river.readUInt16(); 87 | 88 | region.Buildables = new List(); 89 | 90 | for (ushort k = 0; k < region.Count; k++) 91 | { 92 | BuildableData buildableData = new(); 93 | 94 | buildableData.Position = river.readSingleVector3(); 95 | buildableData.Rotation = river.readSingleQuaternion(); 96 | buildableData.AssetId = river.readUInt16(); 97 | 98 | region.Buildables.Add(buildableData); 99 | } 100 | 101 | content.BuildableRegions.Add(region); 102 | } 103 | } 104 | river.closeRiver(); 105 | 106 | return content; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Buildables/BuildableData.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Unturned.Unity; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Buildables 4 | { 5 | public class BuildableData 6 | { 7 | public Vector3 Position { get; set; } 8 | public EulerAngles Rotation { get; set; } 9 | public ushort AssetId { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Buildables/BuildableRegionData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Buildables 4 | { 5 | public class BuildableRegionData 6 | { 7 | public ushort Count { get; set; } 8 | public byte RegionX { get; set; } 9 | public byte RegionY { get; set; } 10 | public List Buildables { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/FaunaDataContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnturnedMapMergeTool.Models.Contents.Faunas; 7 | using UnturnedMapMergeTool.Unturned; 8 | 9 | namespace UnturnedMapMergeTool.Models.Contents 10 | { 11 | public class FaunaDataContent 12 | { 13 | public FaunaDataContent(byte saveDataVersion, byte tablesCount, ushort spawnpointsCount) 14 | { 15 | SaveDataVersion = saveDataVersion; 16 | TablesCount = tablesCount; 17 | SpawnPointsCount = spawnpointsCount; 18 | 19 | Tables = new(); 20 | SpawnPoints = new(); 21 | 22 | } 23 | 24 | public FaunaDataContent() 25 | { 26 | 27 | } 28 | 29 | public byte SaveDataVersion { get; set; } 30 | 31 | public byte TablesCount { get; set; } 32 | public List Tables { get; set; } 33 | 34 | public ushort SpawnPointsCount { get; set; } 35 | public List SpawnPoints { get; set; } 36 | 37 | public void SaveToFile(string fileNamePath) 38 | { 39 | River river = new(fileNamePath); 40 | 41 | river.writeByte(SaveDataVersion); 42 | river.writeByte(TablesCount); 43 | 44 | foreach (AnimalTableData animalTable in Tables) 45 | { 46 | river.writeColor(animalTable.Color); 47 | river.writeString(animalTable.Name); 48 | river.writeUInt16(animalTable.TableId); 49 | river.writeByte(animalTable.TiersCount); 50 | 51 | foreach (AnimalTierData animalTier in animalTable.Tiers) 52 | { 53 | river.writeString(animalTier.Name); 54 | river.writeSingle(animalTier.Chance); 55 | river.writeByte(animalTier.SpawnsCount); 56 | 57 | foreach (AnimalSpawnData animalSpawn in animalTier.Spawns) 58 | { 59 | river.writeUInt16(animalSpawn.Animal); 60 | } 61 | } 62 | } 63 | 64 | river.writeUInt16(SpawnPointsCount); 65 | foreach (AnimalSpawnpointData animalSpawnPoint in SpawnPoints) 66 | { 67 | river.writeByte(animalSpawnPoint.Type); 68 | river.writeSingleVector3(animalSpawnPoint.Point); 69 | } 70 | 71 | river.closeRiver(); 72 | } 73 | 74 | public static FaunaDataContent FromFile(string fileNamePath) 75 | { 76 | River river = new(fileNamePath); 77 | 78 | FaunaDataContent content = new(); 79 | content.Tables = new(); 80 | content.SpawnPoints = new(); 81 | 82 | content.SaveDataVersion = river.readByte(); 83 | 84 | content.TablesCount = river.readByte(); 85 | 86 | for (byte i = 0; i < content.TablesCount; i++) 87 | { 88 | AnimalTableData animalTable = new(); 89 | animalTable.Tiers = new(); 90 | 91 | animalTable.Color = river.readColor(); 92 | animalTable.Name = river.readString(); 93 | if (content.SaveDataVersion > 2) 94 | { 95 | animalTable.TableId = river.readUInt16(); 96 | } else 97 | { 98 | animalTable.TableId = 0; 99 | } 100 | 101 | animalTable.TiersCount = river.readByte(); 102 | 103 | for (byte j = 0; j < animalTable.TiersCount; j++) 104 | { 105 | AnimalTierData animalTier = new(); 106 | animalTier.Spawns = new(); 107 | 108 | animalTier.Name = river.readString(); 109 | animalTier.Chance = river.readSingle(); 110 | animalTier.SpawnsCount = river.readByte(); 111 | 112 | for (byte k = 0; k < animalTier.SpawnsCount; k++) 113 | { 114 | AnimalSpawnData animalSpawn = new(); 115 | animalSpawn.Animal = river.readUInt16(); 116 | 117 | animalTier.Spawns.Add(animalSpawn); 118 | } 119 | 120 | animalTable.Tiers.Add(animalTier); 121 | } 122 | 123 | content.Tables.Add(animalTable); 124 | } 125 | 126 | content.SpawnPointsCount = river.readUInt16(); 127 | for (ushort l = 0; l < content.SpawnPointsCount; l++) 128 | { 129 | AnimalSpawnpointData animalSpawnpoint = new(); 130 | animalSpawnpoint.Type = river.readByte(); 131 | animalSpawnpoint.Point = river.readSingleVector3(); 132 | 133 | content.SpawnPoints.Add(animalSpawnpoint); 134 | } 135 | 136 | 137 | river.closeRiver(); 138 | return content; 139 | } 140 | 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Faunas/AnimalSpawnData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents.Faunas 8 | { 9 | public class AnimalSpawnData 10 | { 11 | public ushort Animal { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Faunas/AnimalSpawnpointData.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Unturned.Unity; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Faunas 4 | { 5 | public class AnimalSpawnpointData 6 | { 7 | public byte Type { get; set; } 8 | public Vector3 Point { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Faunas/AnimalTableData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Unturned.Unity; 3 | 4 | namespace UnturnedMapMergeTool.Models.Contents.Faunas 5 | { 6 | public class AnimalTableData 7 | { 8 | public Color Color { get; set; } 9 | public string Name { get; set; } 10 | public ushort TableId { get; set; } 11 | public byte TiersCount { get; set; } 12 | public List Tiers { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Faunas/AnimalTierData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents.Faunas 8 | { 9 | public class AnimalTierData 10 | { 11 | public string Name { get; set; } 12 | public float Chance { get; set; } 13 | public byte SpawnsCount { get; set; } 14 | public List Spawns { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Flags/FlagData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnturnedMapMergeTool.Unturned.Unity; 7 | 8 | namespace UnturnedMapMergeTool.Models.Contents.Flags 9 | { 10 | public class FlagData 11 | { 12 | public Vector3 Point { get; set; } 13 | public float Width { get; set; } 14 | public float Height { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/FlagsData/FlagDataData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents.FlagsData 8 | { 9 | public class FlagDataData 10 | { 11 | public string DifficultyGuid { get; set; } 12 | public byte MaxZombies { get; set; } 13 | public bool SpawnZombies { get; set; } 14 | public bool HyperAgro { get; set; } 15 | public int MaxBossZombies { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/FlagsDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Models.Contents.Flags; 3 | using UnturnedMapMergeTool.Unturned; 4 | 5 | namespace UnturnedMapMergeTool.Models.Contents 6 | { 7 | public class FlagsDataContent 8 | { 9 | public FlagsDataContent() 10 | { 11 | 12 | } 13 | public FlagsDataContent(byte saveDataVersion, byte count) 14 | { 15 | SaveDataVersion = saveDataVersion; 16 | Count = count; 17 | 18 | Flags = new(); 19 | } 20 | 21 | public byte SaveDataVersion { get; set; } 22 | public byte Count { get; set; } 23 | 24 | public List Flags { get; set; } 25 | 26 | public void SaveToFile(string fileNamePath) 27 | { 28 | River river = new River(fileNamePath); 29 | 30 | river.writeByte(SaveDataVersion); 31 | river.writeByte(Count); 32 | 33 | foreach (FlagData flag in Flags) 34 | { 35 | river.writeSingleVector3(flag.Point); 36 | river.writeSingle(flag.Width); 37 | river.writeSingle(flag.Height); 38 | } 39 | 40 | river.closeRiver(); 41 | } 42 | 43 | public static FlagsDataContent FromFile(string fileNamePath) 44 | { 45 | River river = new(fileNamePath); 46 | 47 | FlagsDataContent content = new(); 48 | content.Flags = new(); 49 | 50 | content.SaveDataVersion = river.readByte(); 51 | content.Count = river.readByte(); 52 | 53 | for (byte i = 0; i < content.Count; i++) 54 | { 55 | FlagData flagData = new(); 56 | content.Flags.Add(flagData); 57 | 58 | flagData.Point = river.readSingleVector3(); 59 | flagData.Width = river.readSingle(); 60 | flagData.Height = river.readSingle(); 61 | 62 | if (content.SaveDataVersion < 4) 63 | { 64 | flagData.Height *= 0.5f; 65 | flagData.Width *= 0.5f; 66 | } 67 | } 68 | 69 | river.closeRiver(); 70 | return content; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/FlagsDataDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Models.Contents.FlagsData; 3 | using UnturnedMapMergeTool.Unturned; 4 | 5 | namespace UnturnedMapMergeTool.Models.Contents 6 | { 7 | public class FlagsDataDataContent 8 | { 9 | public FlagsDataDataContent(byte saveDataVersion, byte count) 10 | { 11 | SaveDataVersion = saveDataVersion; 12 | Count = count; 13 | 14 | FlagsData = new(); 15 | } 16 | 17 | public FlagsDataDataContent() 18 | { 19 | 20 | } 21 | 22 | public byte SaveDataVersion { get; set; } 23 | public byte Count { get; set; } 24 | public List FlagsData { get; set; } 25 | 26 | public void SaveToFile(string fileNamePath) 27 | { 28 | River river = new(fileNamePath); 29 | 30 | river.writeByte(SaveDataVersion); 31 | river.writeByte(Count); 32 | 33 | foreach (FlagDataData flagData in FlagsData) 34 | { 35 | river.writeString(flagData.DifficultyGuid); 36 | river.writeByte(flagData.MaxZombies); 37 | river.writeBoolean(flagData.SpawnZombies); 38 | river.writeBoolean(flagData.HyperAgro); 39 | river.writeInt32(flagData.MaxBossZombies); 40 | } 41 | 42 | river.closeRiver(); 43 | } 44 | 45 | public static FlagsDataDataContent FromFile(string fileNamePath) 46 | { 47 | River river = new(fileNamePath); 48 | 49 | FlagsDataDataContent content = new(); 50 | 51 | content.SaveDataVersion = river.readByte(); 52 | content.Count = river.readByte(); 53 | content.FlagsData = new(); 54 | 55 | for (int i = 0; i < content.Count; i++) 56 | { 57 | FlagDataData flagData = new(); 58 | content.FlagsData.Add(flagData); 59 | 60 | flagData.DifficultyGuid = river.readString(); 61 | 62 | flagData.MaxZombies = 64; 63 | if (content.SaveDataVersion > 1) 64 | { 65 | flagData.MaxZombies = river.readByte(); 66 | } 67 | 68 | flagData.SpawnZombies = true; 69 | if (content.SaveDataVersion > 2) 70 | { 71 | flagData.SpawnZombies = river.readBoolean(); 72 | } 73 | 74 | flagData.HyperAgro = false; 75 | if (content.SaveDataVersion >= 4) 76 | { 77 | flagData.HyperAgro = river.readBoolean(); 78 | } 79 | 80 | flagData.MaxBossZombies = -1; 81 | if (content.SaveDataVersion >= 5) 82 | { 83 | flagData.MaxBossZombies = river.readInt32(); 84 | } 85 | } 86 | 87 | river.closeRiver(); 88 | return content; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Items/ItemSpawnData.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Models.Contents.Items 2 | { 3 | public class ItemSpawnData 4 | { 5 | public ushort ItemId { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Items/ItemTableData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnturnedMapMergeTool.Unturned.Unity; 7 | 8 | namespace UnturnedMapMergeTool.Models.Contents.Items 9 | { 10 | public class ItemTableData 11 | { 12 | public Color Color { get; set; } 13 | public string Name { get; set; } 14 | public ushort TableId { get; set; } 15 | public byte TiersCount { get; set; } 16 | public List Tiers { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Items/ItemTierData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Items 4 | { 5 | public class ItemTierData 6 | { 7 | public string Name { get; set; } 8 | public float Chance { get; set; } 9 | public byte SpawnsCount { get; set; } 10 | public List Spawns { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/ItemsDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Models.Contents.Items; 3 | using UnturnedMapMergeTool.Models.Contents.Vehicles; 4 | using UnturnedMapMergeTool.Unturned; 5 | 6 | namespace UnturnedMapMergeTool.Models.Contents 7 | { 8 | public class ItemsDataContent 9 | { 10 | public ItemsDataContent(byte saveDataVersion, byte tablesCount) 11 | { 12 | SaveDataVersion = saveDataVersion; 13 | TablesCount = tablesCount; 14 | 15 | Tables = new(); 16 | } 17 | 18 | public ItemsDataContent() 19 | { 20 | 21 | } 22 | 23 | public byte SaveDataVersion { get; set; } 24 | public byte TablesCount { get; set; } 25 | public List Tables { get; set; } 26 | 27 | public void SaveToFile(string fileNamePath) 28 | { 29 | River river = new(fileNamePath); 30 | 31 | river.writeByte(SaveDataVersion); 32 | river.writeByte(TablesCount); 33 | 34 | foreach (ItemTableData itemTable in Tables) 35 | { 36 | river.writeColor(itemTable.Color); 37 | river.writeString(itemTable.Name); 38 | river.writeUInt16(itemTable.TableId); 39 | river.writeByte(itemTable.TiersCount); 40 | 41 | foreach (ItemTierData itemTier in itemTable.Tiers) 42 | { 43 | river.writeString(itemTier.Name); 44 | river.writeSingle(itemTier.Chance); 45 | river.writeByte(itemTier.SpawnsCount); 46 | 47 | foreach (ItemSpawnData itemSpawn in itemTier.Spawns) 48 | { 49 | river.writeUInt16(itemSpawn.ItemId); 50 | } 51 | } 52 | } 53 | 54 | river.closeRiver(); 55 | } 56 | 57 | public static ItemsDataContent FromFile(string fileNamePath) 58 | { 59 | River river = new(fileNamePath); 60 | 61 | ItemsDataContent content = new(); 62 | 63 | content.SaveDataVersion = river.readByte(); 64 | 65 | if (content.SaveDataVersion > 1 && content.SaveDataVersion < 3) 66 | { 67 | river.readSteamID(); 68 | } 69 | 70 | content.TablesCount = river.readByte(); 71 | content.Tables = new(); 72 | 73 | for (byte i = 0; i < content.TablesCount; i++) 74 | { 75 | ItemTableData itemTable = new(); 76 | itemTable.Color = river.readColor(); 77 | itemTable.Name = river.readString(); 78 | 79 | if (content.SaveDataVersion > 3) 80 | { 81 | itemTable.TableId = river.readUInt16(); 82 | } 83 | else 84 | { 85 | itemTable.TableId = 0; 86 | } 87 | 88 | itemTable.TiersCount = river.readByte(); 89 | itemTable.Tiers = new(); 90 | 91 | for (byte j = 0; j < itemTable.TiersCount; j++) 92 | { 93 | ItemTierData itemTier = new(); 94 | itemTier.Name = river.readString(); 95 | itemTier.Chance = river.readSingle(); 96 | itemTier.SpawnsCount = river.readByte(); 97 | itemTier.Spawns = new(); 98 | 99 | for (byte k = 0; k < itemTier.SpawnsCount; k++) 100 | { 101 | ItemSpawnData itemSpawn = new(); 102 | itemSpawn.ItemId = river.readUInt16(); 103 | itemTier.Spawns.Add(itemSpawn); 104 | } 105 | 106 | itemTable.Tiers.Add(itemTier); 107 | } 108 | 109 | content.Tables.Add(itemTable); 110 | } 111 | 112 | river.closeRiver(); 113 | return content; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Jars/ItemRegionData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Models.Contents.Animals; 3 | 4 | namespace UnturnedMapMergeTool.Models.Contents.Jars 5 | { 6 | public class ItemRegionData 7 | { 8 | public byte RegionX { get; set; } 9 | public byte RegionY { get; set; } 10 | public ushort SpawnpointsCount { get; set; } 11 | public List Spawnpoints { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Jars/ItemSpawnpointData.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Unturned.Unity; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Jars 4 | { 5 | public class ItemSpawnpointData 6 | { 7 | public byte Type { get; set; } 8 | public Vector3 Point { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/JarsDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using UnturnedMapMergeTool.Models.Contents.Jars; 4 | using UnturnedMapMergeTool.Unturned; 5 | 6 | namespace UnturnedMapMergeTool.Models.Contents 7 | { 8 | public class JarsDataContent 9 | { 10 | public JarsDataContent() 11 | { 12 | 13 | } 14 | 15 | public JarsDataContent(byte saveDataVersion) 16 | { 17 | SaveDataVersion = saveDataVersion; 18 | 19 | ItemRegions = new List(); 20 | 21 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 22 | { 23 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 24 | { 25 | ItemRegionData itemRegion = new() 26 | { 27 | RegionX = i, 28 | RegionY = j, 29 | SpawnpointsCount = 0, 30 | Spawnpoints = new List() 31 | }; 32 | 33 | ItemRegions.Add(itemRegion); 34 | } 35 | } 36 | } 37 | 38 | public byte SaveDataVersion { get; set; } 39 | public List ItemRegions { get; set; } 40 | 41 | public void SaveToFile(string fileNamePath) 42 | { 43 | River river = new(fileNamePath); 44 | river.writeByte(SaveDataVersion); 45 | 46 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 47 | { 48 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 49 | { 50 | ItemRegionData regionData = ItemRegions.First(x => x.RegionX == i && x.RegionY == j); 51 | river.writeUInt16(regionData.SpawnpointsCount); 52 | 53 | foreach (ItemSpawnpointData itemSpawnpoint in regionData.Spawnpoints) 54 | { 55 | river.writeByte(itemSpawnpoint.Type); 56 | river.writeSingleVector3(itemSpawnpoint.Point); 57 | } 58 | } 59 | } 60 | 61 | river.closeRiver(); 62 | } 63 | 64 | public static JarsDataContent FromFile(string fileNamePath) 65 | { 66 | River river = new(fileNamePath); 67 | 68 | JarsDataContent content = new(); 69 | 70 | content.SaveDataVersion = river.readByte(); 71 | 72 | content.ItemRegions = new List(); 73 | 74 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 75 | { 76 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 77 | { 78 | ItemRegionData region = new() 79 | { 80 | RegionX = i, 81 | RegionY = j 82 | }; 83 | 84 | region.SpawnpointsCount = river.readUInt16(); 85 | 86 | region.Spawnpoints = new List(); 87 | 88 | for (ushort k = 0; k < region.SpawnpointsCount; k++) 89 | { 90 | ItemSpawnpointData itemSpawnpoint = new(); 91 | 92 | itemSpawnpoint.Type = river.readByte(); 93 | itemSpawnpoint.Point = river.readSingleVector3(); 94 | 95 | region.Spawnpoints.Add(itemSpawnpoint); 96 | } 97 | 98 | content.ItemRegions.Add(region); 99 | } 100 | } 101 | 102 | river.closeRiver(); 103 | 104 | return content; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Navigations/NavmeshTileData.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Models.Contents.Navigations 2 | { 3 | public class NavmeshTileData 4 | { 5 | public ushort TrisCount { get; set; } 6 | public ushort[] Tris { get; set; } 7 | public ushort VertsCount { get; set; } 8 | public NavmeshTileVertData[] Verts { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Navigations/NavmeshTileVertData.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Models.Contents.Navigations 2 | { 3 | public class NavmeshTileVertData 4 | { 5 | public int X { get; set; } 6 | public int Y { get; set; } 7 | public int Z { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/NavigationsDataContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Net.Mime; 6 | using System.Reflection.Metadata; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using UnturnedMapMergeTool.Models.Contents.Navigations; 10 | using UnturnedMapMergeTool.Unturned; 11 | using UnturnedMapMergeTool.Unturned.Unity; 12 | 13 | namespace UnturnedMapMergeTool.Models.Contents 14 | { 15 | public class NavigationsDataContent 16 | { 17 | public byte SaveDataNavigationVersion { get; set; } 18 | public Vector3 ForcedBoundsCenter { get; set; } 19 | public Vector3 ForcedBoundsSize { get; set; } 20 | public byte TileXCount { get; set; } 21 | public byte TileZCount { get; set; } 22 | 23 | public NavmeshTileData[] NavmeshTiles { get; set; } 24 | 25 | public void SaveToFile(string fileNamePath) 26 | { 27 | River river = new(fileNamePath); 28 | 29 | river.writeByte(SaveDataNavigationVersion); 30 | river.writeSingleVector3(ForcedBoundsCenter); 31 | river.writeSingleVector3(ForcedBoundsSize); 32 | river.writeByte(TileXCount); 33 | river.writeByte(TileZCount); 34 | 35 | for (int i = 0; i < TileZCount; i++) 36 | { 37 | for (int j = 0; j < TileXCount; j++) 38 | { 39 | int index = j + i * TileXCount; 40 | NavmeshTileData navmeshTile = NavmeshTiles[index]; 41 | 42 | river.writeUInt16(navmeshTile.TrisCount); 43 | for (int k = 0; k < navmeshTile.TrisCount; k++) 44 | { 45 | river.writeUInt16(navmeshTile.Tris[k]); 46 | } 47 | river.writeUInt16(navmeshTile.VertsCount); 48 | for (int l = 0; l < navmeshTile.VertsCount; l++) 49 | { 50 | NavmeshTileVertData navmeshTileVert = navmeshTile.Verts[l]; 51 | river.writeInt32(navmeshTileVert.X); 52 | river.writeInt32(navmeshTileVert.Y); 53 | river.writeInt32(navmeshTileVert.Z); 54 | } 55 | } 56 | } 57 | 58 | river.closeRiver(); 59 | } 60 | 61 | public static NavigationsDataContent FromFile(string fileNamePath) 62 | { 63 | River river = new(fileNamePath); 64 | 65 | NavigationsDataContent content = new(); 66 | 67 | content.SaveDataNavigationVersion = river.readByte(); 68 | content.ForcedBoundsCenter = river.readSingleVector3(); 69 | content.ForcedBoundsSize = river.readSingleVector3(); 70 | content.TileXCount = river.readByte(); 71 | content.TileZCount = river.readByte(); 72 | 73 | content.NavmeshTiles = new NavmeshTileData[content.TileXCount * content.TileZCount]; 74 | 75 | for (int i = 0; i < content.TileZCount; i++) 76 | { 77 | for (int j = 0; j < content.TileXCount; j++) 78 | { 79 | NavmeshTileData navmeshTile = new(); 80 | 81 | int index = j + i * content.TileXCount; 82 | 83 | content.NavmeshTiles[index] = navmeshTile; 84 | 85 | navmeshTile.TrisCount = river.readUInt16(); 86 | navmeshTile.Tris = new ushort[navmeshTile.TrisCount]; 87 | for (int k = 0; k < navmeshTile.TrisCount; k++) 88 | { 89 | navmeshTile.Tris[k] = river.readUInt16(); 90 | } 91 | 92 | navmeshTile.VertsCount = river.readUInt16(); 93 | navmeshTile.Verts = new NavmeshTileVertData[navmeshTile.VertsCount]; 94 | for (int l = 0; l < navmeshTile.VertsCount; l++) 95 | { 96 | NavmeshTileVertData navmeshTileVert = new(); 97 | navmeshTileVert.X = river.readInt32(); 98 | navmeshTileVert.Y = river.readInt32(); 99 | navmeshTileVert.Z = river.readInt32(); 100 | 101 | navmeshTile.Verts[l] = navmeshTileVert; 102 | } 103 | } 104 | } 105 | 106 | river.closeRiver(); 107 | return content; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Nodes/LocationNodeData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents.Nodes 8 | { 9 | public class LocationNodeData 10 | { 11 | public string LocationName { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Nodes/NodeData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using UnturnedMapMergeTool.Unturned.Unity; 8 | 9 | namespace UnturnedMapMergeTool.Models.Contents.Nodes 10 | { 11 | public class NodeData 12 | { 13 | public Vector3 Point { get; set; } 14 | public byte Type { get; set; } 15 | public string LocationName { get; set; } 16 | public float Radius { get; set; } 17 | public bool IsHeight { get; set; } 18 | public bool NoWeapons { get; set; } 19 | public bool NoBuildables { get; set; } 20 | public ushort AssetId { get; set; } 21 | public uint Cost { get; set; } 22 | public byte DeadzoneType { get; set; } 23 | public byte Shape { get; set; } 24 | public Vector3 Bounds { get; set; } 25 | public bool NoWater { get; set; } 26 | public bool NoLighting { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Nodes/PurchaseNodeData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents.Nodes 8 | { 9 | public class PurchaseNodeData 10 | { 11 | public float Radius { get; set; } 12 | public ushort AssetId { get; set; } 13 | public uint Cost { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Nodes/SafezoneNodeData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents.Nodes 8 | { 9 | public class SafezoneNodeData 10 | { 11 | public float Radius { get; set; } 12 | public bool IsHeight { get; set; } 13 | public bool NoWeapons { get; set; } 14 | public bool NoBuildables { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/NodesDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using UnturnedMapMergeTool.Models.Contents.Nodes; 4 | using UnturnedMapMergeTool.Unturned; 5 | using UnturnedMapMergeTool.Unturned.Unity; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents 8 | { 9 | public class NodesDataContent 10 | { 11 | public NodesDataContent() 12 | { 13 | 14 | } 15 | 16 | public NodesDataContent(byte saveDataVersion, byte count) 17 | { 18 | SaveDataVersion = saveDataVersion; 19 | Count = count; 20 | 21 | Nodes = new List(); 22 | } 23 | 24 | public byte SaveDataVersion { get; set; } 25 | public byte Count { get; set; } 26 | 27 | public List Nodes { get; set; } 28 | 29 | public void SaveToFile(string fileNamePath) 30 | { 31 | River river = new River(fileNamePath); 32 | 33 | river.writeByte(SaveDataVersion); 34 | river.writeByte(Count); 35 | 36 | foreach (NodeData node in Nodes) 37 | { 38 | river.writeSingleVector3(node.Point); 39 | river.writeByte(node.Type); 40 | if (node.Type == 0) 41 | { 42 | // Location 43 | river.writeString(node.LocationName); 44 | } 45 | else if (node.Type == 1) 46 | { 47 | // Safezone 48 | river.writeSingle(node.Radius); 49 | river.writeBoolean(node.IsHeight); 50 | river.writeBoolean(node.NoWeapons); 51 | river.writeBoolean(node.NoBuildables); 52 | } 53 | else if (node.Type == 2) 54 | { 55 | // Purchase 56 | river.writeSingle(node.Radius); 57 | river.writeUInt16(node.AssetId); 58 | river.writeUInt32(node.Cost); 59 | } 60 | else if (node.Type == 3) 61 | { 62 | // Arena 63 | river.writeSingle(node.Radius); 64 | } 65 | else if (node.Type == 4) 66 | { 67 | // Deadzone 68 | river.writeSingle(node.Radius); 69 | river.writeByte(node.DeadzoneType); 70 | } 71 | else if (node.Type == 5) 72 | { 73 | // Airdrop 74 | river.writeUInt16(node.AssetId); 75 | } 76 | else if (node.Type == 6) 77 | { 78 | // Effect 79 | river.writeByte(node.Shape); 80 | river.writeSingle(node.Radius); 81 | river.writeSingleVector3(node.Bounds); 82 | river.writeUInt16(node.AssetId); 83 | river.writeBoolean(node.NoWater); 84 | river.writeBoolean(node.NoLighting); 85 | } 86 | } 87 | 88 | river.closeRiver(); 89 | } 90 | 91 | public static NodesDataContent FromFile(string fileNamePath) 92 | { 93 | River river = new(fileNamePath); 94 | 95 | NodesDataContent content = new(); 96 | content.Nodes = new List(); 97 | 98 | content.SaveDataVersion = river.readByte(); 99 | content.Count = river.readByte(); 100 | 101 | for (byte i = 0; i < content.Count; i++) 102 | { 103 | NodeData node = new NodeData(); 104 | content.Nodes.Add(node); 105 | 106 | node.Point = river.readSingleVector3(); 107 | node.Type = river.readByte(); 108 | 109 | 110 | if (node.Type == 0) 111 | { 112 | // Location 113 | node.LocationName = river.readString(); 114 | } 115 | else if (node.Type == 1) 116 | { 117 | // Safezone 118 | node.Radius = river.readSingle(); 119 | if (content.SaveDataVersion > 1) 120 | { 121 | node.IsHeight = river.readBoolean(); 122 | } 123 | if (content.SaveDataVersion > 4) 124 | { 125 | node.NoWeapons = river.readBoolean(); 126 | } 127 | if (content.SaveDataVersion > 4) 128 | { 129 | node.NoBuildables = river.readBoolean(); 130 | } 131 | } else if (node.Type == 2) 132 | { 133 | // Purchase 134 | node.Radius = river.readSingle(); 135 | node.AssetId = river.readUInt16(); 136 | node.Cost = river.readUInt32(); 137 | } else if (node.Type == 3) 138 | { 139 | // Arena 140 | node.Radius = river.readSingle(); 141 | if (content.SaveDataVersion < 6) 142 | { 143 | node.Radius *= 0.5f; 144 | } 145 | } else if (node.Type == 4) 146 | { 147 | // Deadzone 148 | node.Radius = river.readSingle(); 149 | node.DeadzoneType = 0; 150 | if (content.SaveDataVersion > 6) 151 | { 152 | node.DeadzoneType = river.readByte(); 153 | } 154 | } else if (node.Type == 5) 155 | { 156 | // Airdrop 157 | node.AssetId = river.readUInt16(); 158 | } else if (node.Type == 6) 159 | { 160 | // Effect 161 | node.Shape = 0; 162 | if (content.SaveDataVersion > 2) 163 | { 164 | node.Shape = river.readByte(); 165 | } 166 | node.Radius = river.readSingle(); 167 | node.Bounds = Vector3.one; 168 | if (content.SaveDataVersion > 2) 169 | { 170 | node.Bounds = river.readSingleVector3(); 171 | } 172 | node.AssetId = river.readUInt16(); 173 | node.NoWater = river.readBoolean(); 174 | node.NoLighting = false; 175 | if (content.SaveDataVersion > 3) 176 | { 177 | node.NoLighting = river.readBoolean(); 178 | } 179 | } 180 | } 181 | 182 | river.closeRiver(); 183 | return content; 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/ObjectDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using UnturnedMapMergeTool.Models.Contents.Objects; 4 | using UnturnedMapMergeTool.Unturned; 5 | using UnturnedMapMergeTool.Unturned.Unity; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents 8 | { 9 | public class ObjectDataContent 10 | { 11 | public byte SaveDataVersion { get; set; } 12 | public CSteamID SteamID { get; set; } 13 | public uint AvailableInstanceId { get; set; } 14 | public byte[] Hash { get; set; } 15 | 16 | public List ObjectRegions { get; set; } 17 | 18 | public ObjectDataContent() 19 | { 20 | 21 | } 22 | 23 | public ObjectDataContent(byte saveDataVersion, CSteamID steamID, uint availableInstanceId, byte[] hash = null) 24 | { 25 | SaveDataVersion = saveDataVersion; 26 | SteamID = steamID; 27 | AvailableInstanceId = availableInstanceId; 28 | Hash = hash; 29 | 30 | ObjectRegions = new List(); 31 | 32 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 33 | { 34 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 35 | { 36 | ObjectRegionData objectRegionData = new() 37 | { 38 | RegionX = i, 39 | RegionY = j, 40 | Count = 0, 41 | Objects = new List() 42 | }; 43 | 44 | ObjectRegions.Add(objectRegionData); 45 | } 46 | } 47 | } 48 | 49 | 50 | public void SaveToFile(string fileNamePath) 51 | { 52 | River river = new(fileNamePath); 53 | river.writeByte(SaveDataVersion); 54 | river.writeUInt32(AvailableInstanceId); 55 | 56 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 57 | { 58 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 59 | { 60 | ObjectRegionData regionData = ObjectRegions.FirstOrDefault(x => x.RegionX == i && x.RegionY == j); 61 | river.writeUInt16(regionData.Count); 62 | 63 | foreach (ObjectData objectData in regionData.Objects) 64 | { 65 | river.writeSingleVector3(objectData.Position); 66 | river.writeSingleQuaternion(objectData.Rotation); 67 | river.writeSingleVector3(objectData.LocalScale); 68 | river.writeUInt16(objectData.AssetId); 69 | river.writeGUID(objectData.Guid); 70 | river.writeByte(objectData.PlacementOrigin); 71 | river.writeUInt32(objectData.InstanceId); 72 | river.writeGUID(objectData.CustomMaterialOverride); 73 | river.writeInt32(objectData.MaterialIndexOverride); 74 | river.writeBoolean(objectData.IsOwnedCullingVolumeAllowed); 75 | } 76 | } 77 | } 78 | 79 | river.closeRiver(); 80 | } 81 | 82 | public static ObjectDataContent FromFile(string fileNamePath) 83 | { 84 | River river = new(fileNamePath); 85 | 86 | ObjectDataContent content = new(); 87 | 88 | content.SaveDataVersion = river.readByte(); 89 | 90 | 91 | if (content.SaveDataVersion <= 0) 92 | { 93 | return null; 94 | } 95 | 96 | if (content.SaveDataVersion > 1 && content.SaveDataVersion < 3) 97 | { 98 | content.SteamID = river.readSteamID(); 99 | } 100 | 101 | if (content.SaveDataVersion > 8) 102 | { 103 | content.AvailableInstanceId = river.readUInt32(); 104 | } else 105 | { 106 | content.AvailableInstanceId = 1U; 107 | } 108 | 109 | content.ObjectRegions = new List(); 110 | 111 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 112 | { 113 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 114 | { 115 | ObjectRegionData region = new() 116 | { 117 | RegionX = i, 118 | RegionY = j 119 | }; 120 | region.Count = river.readUInt16(); 121 | 122 | region.Objects = new List(); 123 | 124 | for (ushort k = 0; k < region.Count; k++) 125 | { 126 | ObjectData objectData = new(); 127 | 128 | objectData.Position = river.readSingleVector3(); 129 | objectData.Rotation = river.readSingleQuaternion(); 130 | if (content.SaveDataVersion > 3) 131 | { 132 | objectData.LocalScale = river.readSingleVector3(); 133 | } else 134 | { 135 | objectData.LocalScale = Vector3.one; 136 | } 137 | 138 | objectData.AssetId = river.readUInt16(); 139 | if (content.SaveDataVersion > 5 && content.SaveDataVersion < 10) 140 | { 141 | // What string is that? 142 | river.readString(); 143 | } 144 | 145 | if (content.SaveDataVersion > 7) 146 | { 147 | objectData.Guid = river.readGUID(); 148 | } 149 | 150 | if (content.SaveDataVersion > 6) 151 | { 152 | objectData.PlacementOrigin = river.readByte(); 153 | } 154 | 155 | if (content.SaveDataVersion > 8) 156 | { 157 | objectData.InstanceId = river.readUInt32(); 158 | } else 159 | { 160 | objectData.InstanceId = content.AvailableInstanceId++; 161 | } 162 | 163 | if (content.SaveDataVersion >= 11) 164 | { 165 | objectData.CustomMaterialOverride = river.readGUID(); 166 | objectData.MaterialIndexOverride = river.readInt32(); 167 | } 168 | 169 | if (content.SaveDataVersion >= 12) 170 | { 171 | objectData.IsOwnedCullingVolumeAllowed = river.readBoolean(); 172 | } else 173 | { 174 | objectData.IsOwnedCullingVolumeAllowed = true; 175 | } 176 | 177 | region.Objects.Add(objectData); 178 | } 179 | 180 | content.ObjectRegions.Add(region); 181 | } 182 | } 183 | 184 | content.Hash = river.getHash(); 185 | river.closeRiver(); 186 | 187 | return content; 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Objects/ObjectData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnturnedMapMergeTool.Unturned.Unity; 3 | 4 | namespace UnturnedMapMergeTool.Models.Contents.Objects 5 | { 6 | public class ObjectData 7 | { 8 | public Vector3 Position { get; set; } 9 | public EulerAngles Rotation { get; set; } 10 | public Vector3 LocalScale { get; set; } 11 | public ushort AssetId { get; set; } 12 | public Guid Guid { get; set; } 13 | public byte PlacementOrigin { get; set; } 14 | public uint InstanceId { get; set; } 15 | public Guid CustomMaterialOverride { get; set; } 16 | public int MaterialIndexOverride { get; set; } 17 | public bool IsOwnedCullingVolumeAllowed { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Objects/ObjectRegionData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Objects 4 | { 5 | public class ObjectRegionData 6 | { 7 | public ushort Count { get; set; } 8 | public byte RegionX { get; set; } 9 | public byte RegionY { get; set; } 10 | public List Objects { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Paths/PathJointData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnturnedMapMergeTool.Unturned.Unity; 7 | 8 | namespace UnturnedMapMergeTool.Models.Contents.Paths 9 | { 10 | public class PathJointData 11 | { 12 | public Vector3 Vertex { get; set; } 13 | public Vector3[] Tangents { get; set; } 14 | public byte RoadMode { get; set; } 15 | public float Offset { get; set; } 16 | public bool IgnoreTerrain { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Paths/PathLineData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents.Paths 8 | { 9 | public class PathLineData 10 | { 11 | public ushort Count { get; set; } 12 | public byte Material { get; set; } 13 | public bool NewLoop { get; set; } 14 | 15 | public List Joints { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/PathsDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data; 3 | using UnturnedMapMergeTool.Models.Contents.Paths; 4 | using UnturnedMapMergeTool.Models.Contents.Trees; 5 | using UnturnedMapMergeTool.Unturned; 6 | using UnturnedMapMergeTool.Unturned.Unity; 7 | 8 | namespace UnturnedMapMergeTool.Models.Contents 9 | { 10 | public class PathsDataContent 11 | { 12 | public PathsDataContent(byte saveDataPathsVersion, ushort count) 13 | { 14 | SaveDataPathsVersion = saveDataPathsVersion; 15 | Count = count; 16 | 17 | PathLines = new(); 18 | } 19 | 20 | public PathsDataContent() 21 | { 22 | 23 | } 24 | 25 | public byte SaveDataPathsVersion { get; set; } 26 | public ushort Count { get; set; } 27 | 28 | public List PathLines { get; set; } 29 | 30 | 31 | public void SaveToFile(string fileNamePath) 32 | { 33 | River river = new(fileNamePath); 34 | river.writeByte(SaveDataPathsVersion); 35 | river.writeUInt16(Count); 36 | 37 | foreach (PathLineData pathLine in PathLines) 38 | { 39 | river.writeUInt16(pathLine.Count); 40 | river.writeByte(pathLine.Material); 41 | river.writeBoolean(pathLine.NewLoop); 42 | 43 | foreach (PathJointData pathJoin in pathLine.Joints) 44 | { 45 | river.writeSingleVector3(pathJoin.Vertex); 46 | river.writeSingleVector3(pathJoin.Tangents[0]); 47 | river.writeSingleVector3(pathJoin.Tangents[1]); 48 | river.writeByte(pathJoin.RoadMode); 49 | river.writeSingle(pathJoin.Offset); 50 | river.writeBoolean(pathJoin.IgnoreTerrain); 51 | } 52 | } 53 | 54 | river.closeRiver(); 55 | } 56 | 57 | public static PathsDataContent FromFile(string fileNamePath) 58 | { 59 | River river = new(fileNamePath); 60 | 61 | PathsDataContent content = new(); 62 | 63 | content.SaveDataPathsVersion = river.readByte(); 64 | content.Count = river.readUInt16(); 65 | content.PathLines = new List(); 66 | 67 | for (ushort i = 0; i < content.Count; i++) 68 | { 69 | PathLineData pathLine = new(); 70 | content.PathLines.Add(pathLine); 71 | 72 | pathLine.Count = river.readUInt16(); 73 | pathLine.Material = river.readByte(); 74 | pathLine.NewLoop = content.SaveDataPathsVersion > 2 && river.readBoolean(); 75 | pathLine.Joints = new List(); 76 | 77 | for (ushort j = 0; j < pathLine.Count; j++) 78 | { 79 | PathJointData pathJoint = new PathJointData(); 80 | pathLine.Joints.Add(pathJoint); 81 | 82 | pathJoint.Vertex = river.readSingleVector3(); 83 | 84 | pathJoint.Tangents = new Vector3[2]; 85 | if (content.SaveDataPathsVersion > 2) 86 | { 87 | pathJoint.Tangents[0] = river.readSingleVector3(); 88 | pathJoint.Tangents[1] = river.readSingleVector3(); 89 | } 90 | 91 | if (content.SaveDataPathsVersion > 2) 92 | { 93 | pathJoint.RoadMode = river.readByte(); 94 | } else 95 | { 96 | // 2: ERoadMode.FREE 97 | pathJoint.RoadMode = 2; 98 | } 99 | 100 | if (content.SaveDataPathsVersion > 4) 101 | { 102 | pathJoint.Offset = river.readSingle(); 103 | } else 104 | { 105 | pathJoint.Offset = 0; 106 | } 107 | 108 | pathJoint.IgnoreTerrain = content.SaveDataPathsVersion > 3 && river.readBoolean(); 109 | } 110 | } 111 | 112 | river.closeRiver(); 113 | 114 | return content; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Players/PlayerSpawnData.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Unturned.Unity; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Players 4 | { 5 | public class PlayerSpawnData 6 | { 7 | public Vector3 Point { get; set; } 8 | public byte Angle { get; set; } 9 | public bool IsAlt { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/PlayersDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Models.Contents.Players; 3 | using UnturnedMapMergeTool.Unturned; 4 | 5 | namespace UnturnedMapMergeTool.Models.Contents 6 | { 7 | public class PlayersDataContent 8 | { 9 | public PlayersDataContent(byte saveDataVersion, byte count) 10 | { 11 | SaveDataVersion = saveDataVersion; 12 | Count = count; 13 | 14 | Spawns = new(); 15 | } 16 | 17 | public PlayersDataContent() 18 | { 19 | 20 | } 21 | 22 | public byte SaveDataVersion { get; set; } 23 | public byte Count { get; set; } 24 | public List Spawns { get; set; } 25 | 26 | public void SaveToFile(string fileNamePath) 27 | { 28 | River river = new(fileNamePath); 29 | 30 | river.writeByte(SaveDataVersion); 31 | river.writeByte(Count); 32 | 33 | foreach (PlayerSpawnData playerSpawn in Spawns) 34 | { 35 | river.writeSingleVector3(playerSpawn.Point); 36 | river.writeByte(playerSpawn.Angle); 37 | river.writeBoolean(playerSpawn.IsAlt); 38 | } 39 | 40 | river.closeRiver(); 41 | } 42 | 43 | public static PlayersDataContent FromFile(string fileNamePath) 44 | { 45 | River river = new(fileNamePath); 46 | 47 | PlayersDataContent content = new(); 48 | 49 | content.SaveDataVersion = river.readByte(); 50 | if (content.SaveDataVersion > 1 && content.SaveDataVersion < 3) 51 | { 52 | river.readSteamID(); 53 | } 54 | 55 | content.Count = river.readByte(); 56 | content.Spawns = new List(); 57 | 58 | for (int i = 0; i < content.Count; i++) 59 | { 60 | PlayerSpawnData playerSpawn = new(); 61 | 62 | playerSpawn.Point = river.readSingleVector3(); 63 | playerSpawn.Angle = river.readByte(); 64 | playerSpawn.IsAlt = false; 65 | 66 | if (content.SaveDataVersion > 3) 67 | { 68 | playerSpawn.IsAlt = river.readBoolean(); 69 | } 70 | 71 | content.Spawns.Add(playerSpawn); 72 | } 73 | 74 | river.closeRiver(); 75 | 76 | return content; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Roads/RoadMaterialData.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Models.Contents.Roads 2 | { 3 | public class RoadMaterialData 4 | { 5 | public float Width { get; set; } 6 | public float Height { get; set; } 7 | public float Depth { get; set; } 8 | public float Offset { get; set; } 9 | public bool IsConcrete { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/RoadsDataContent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Models.Contents.Roads; 3 | using UnturnedMapMergeTool.Unturned; 4 | 5 | namespace UnturnedMapMergeTool.Models.Contents 6 | { 7 | public class RoadsDataContent 8 | { 9 | public RoadsDataContent() 10 | { 11 | 12 | } 13 | public RoadsDataContent(byte saveDataRoadsVersion, byte count) 14 | { 15 | SaveDataRoadsVersion = saveDataRoadsVersion; 16 | Count = count; 17 | 18 | Materials = new List(); 19 | } 20 | 21 | public byte SaveDataRoadsVersion { get; set; } 22 | public byte Count { get; set; } 23 | 24 | public List Materials { get; set; } 25 | 26 | public void SaveToFile(string fileNamePath) 27 | { 28 | River river = new(fileNamePath); 29 | 30 | river.writeByte(SaveDataRoadsVersion); 31 | river.writeByte(Count); 32 | 33 | foreach (RoadMaterialData roadMaterial in Materials) 34 | { 35 | river.writeSingle(roadMaterial.Width); 36 | river.writeSingle(roadMaterial.Height); 37 | river.writeSingle(roadMaterial.Depth); 38 | river.writeSingle(roadMaterial.Offset); 39 | river.writeBoolean(roadMaterial.IsConcrete); 40 | } 41 | 42 | river.closeRiver(); 43 | } 44 | 45 | public static RoadsDataContent FromFile(string fileNamePath) 46 | { 47 | River river = new(fileNamePath); 48 | 49 | RoadsDataContent content = new(); 50 | content.Materials = new List(); 51 | 52 | content.SaveDataRoadsVersion = river.readByte(); 53 | content.Count = river.readByte(); 54 | 55 | for (int i = 0; i < content.Count; i++) 56 | { 57 | RoadMaterialData roadMaterial = new(); 58 | content.Materials.Add(roadMaterial); 59 | 60 | roadMaterial.Width = river.readSingle(); 61 | roadMaterial.Height = river.readSingle(); 62 | roadMaterial.Depth = river.readSingle(); 63 | if (content.SaveDataRoadsVersion > 1) 64 | { 65 | roadMaterial.Offset = river.readSingle(); 66 | } 67 | roadMaterial.IsConcrete = river.readBoolean(); 68 | } 69 | 70 | river.closeRiver(); 71 | 72 | return content; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Trees/TreeData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnturnedMapMergeTool.Unturned.Unity; 3 | 4 | namespace UnturnedMapMergeTool.Models.Contents.Trees 5 | { 6 | public class TreeData 7 | { 8 | public ushort AssetId { get; set; } 9 | public Guid Guid { get; set; } 10 | public Vector3 Position { get; set; } 11 | public bool IsGenerated { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Trees/TreeRegionData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Models.Contents.Objects; 3 | 4 | namespace UnturnedMapMergeTool.Models.Contents.Trees 5 | { 6 | public class TreeRegionData 7 | { 8 | public ushort Count { get; set; } 9 | public byte RegionX { get; set; } 10 | public byte RegionY { get; set; } 11 | public List Trees { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/TreesDataContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnturnedMapMergeTool.Models.Contents.Trees; 5 | using UnturnedMapMergeTool.Unturned; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents 8 | { 9 | public class TreesDataContent 10 | { 11 | public byte SaveDataTreesVersion { get; set; } 12 | public List TreeRegions { get; set; } 13 | 14 | public TreesDataContent() { } 15 | 16 | public TreesDataContent(byte saveDataTreesVersion) 17 | { 18 | SaveDataTreesVersion = saveDataTreesVersion; 19 | 20 | TreeRegions = new List(); 21 | 22 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 23 | { 24 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 25 | { 26 | TreeRegionData objectRegionData = new() 27 | { 28 | RegionX = i, 29 | RegionY = j, 30 | Count = 0, 31 | Trees = new List() 32 | }; 33 | 34 | TreeRegions.Add(objectRegionData); 35 | } 36 | } 37 | } 38 | 39 | public void SaveToFile(string fileNamePath) 40 | { 41 | River river = new(fileNamePath); 42 | river.writeByte(SaveDataTreesVersion); 43 | 44 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 45 | { 46 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 47 | { 48 | TreeRegionData regionData = TreeRegions.First(x => x.RegionX == i && x.RegionY == j); 49 | river.writeUInt16(regionData.Count); 50 | 51 | foreach (TreeData treeData in regionData.Trees) 52 | { 53 | river.writeUInt16(treeData.AssetId); 54 | river.writeGUID(treeData.Guid); 55 | river.writeSingleVector3(treeData.Position); 56 | river.writeBoolean(treeData.IsGenerated); 57 | } 58 | } 59 | } 60 | 61 | river.closeRiver(); 62 | } 63 | 64 | public static TreesDataContent FromFile(string fileNamePath) 65 | { 66 | River river = new(fileNamePath); 67 | 68 | TreesDataContent content = new(); 69 | 70 | content.SaveDataTreesVersion = river.readByte(); 71 | 72 | content.TreeRegions = new List(); 73 | 74 | for (byte i = 0; i < Regions.WORLD_SIZE; i++) 75 | { 76 | for (byte j = 0; j < Regions.WORLD_SIZE; j++) 77 | { 78 | TreeRegionData region = new() 79 | { 80 | RegionX = i, 81 | RegionY = j 82 | }; 83 | 84 | region.Count = river.readUInt16(); 85 | 86 | region.Trees = new List(); 87 | 88 | for (ushort k = 0; k < region.Count; k++) 89 | { 90 | TreeData treeData = new(); 91 | 92 | treeData.AssetId = river.readUInt16(); 93 | if (content.SaveDataTreesVersion < 6) 94 | { 95 | treeData.Guid = Guid.Empty; 96 | } else 97 | { 98 | treeData.Guid = river.readGUID(); 99 | } 100 | 101 | treeData.Position = river.readSingleVector3(); 102 | treeData.IsGenerated = river.readBoolean(); 103 | 104 | region.Trees.Add(treeData); 105 | } 106 | 107 | content.TreeRegions.Add(region); 108 | } 109 | } 110 | river.closeRiver(); 111 | 112 | return content; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Vehicles/VehicleSpawnData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents.Vehicles 8 | { 9 | public class VehicleSpawnData 10 | { 11 | public ushort VehicleId { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Vehicles/VehicleSpawnpointData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnturnedMapMergeTool.Unturned.Unity; 4 | 5 | namespace UnturnedMapMergeTool.Models.Contents.Vehicles 6 | { 7 | public class VehicleSpawnpointData 8 | { 9 | public byte Type { get; set; } 10 | public Vector3 Point { get; set; } 11 | public byte Angle { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Vehicles/VehicleTableData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnturnedMapMergeTool.Unturned.Unity; 3 | 4 | namespace UnturnedMapMergeTool.Models.Contents.Vehicles 5 | { 6 | public class VehicleTableData 7 | { 8 | public Color Color { get; set; } 9 | public string Name { get; set; } 10 | public ushort TableId { get; set; } 11 | public byte TiersCount { get; set; } 12 | public List Tiers { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Vehicles/VehicleTierData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Vehicles 4 | { 5 | public class VehicleTierData 6 | { 7 | public string Name { get; set; } 8 | public float Chance { get; set; } 9 | public byte SpawnsCount { get; set; } 10 | public List Spawns { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/VehiclesDataContent.cs: -------------------------------------------------------------------------------- 1 | using Serilog; 2 | using System; 3 | using System.Collections.Generic; 4 | using UnturnedMapMergeTool.Models.Contents.Vehicles; 5 | using UnturnedMapMergeTool.Unturned; 6 | 7 | namespace UnturnedMapMergeTool.Models.Contents 8 | { 9 | public class VehiclesDataContent 10 | { 11 | public VehiclesDataContent(byte saveDataVersion, byte tablesCount, ushort spawnpointsCount) 12 | { 13 | SaveDataVersion = saveDataVersion; 14 | TablesCount = tablesCount; 15 | SpawnpointsCount = spawnpointsCount; 16 | 17 | Tables = new(); 18 | Spawnpoints = new(); 19 | } 20 | 21 | public VehiclesDataContent() 22 | { 23 | 24 | } 25 | 26 | public byte SaveDataVersion { get; set; } 27 | 28 | public byte TablesCount { get; set; } 29 | public List Tables { get; set; } 30 | 31 | public ushort SpawnpointsCount { get; set; } 32 | public List Spawnpoints { get; set; } 33 | 34 | public void SaveToFile(string fileNamePath) 35 | { 36 | River river = new(fileNamePath); 37 | 38 | river.writeByte(SaveDataVersion); 39 | river.writeByte(TablesCount); 40 | 41 | foreach (VehicleTableData vehicleTable in Tables) 42 | { 43 | river.writeColor(vehicleTable.Color); 44 | river.writeString(vehicleTable.Name); 45 | river.writeUInt16(vehicleTable.TableId); 46 | river.writeByte(vehicleTable.TiersCount); 47 | 48 | foreach (VehicleTierData vehicleTier in vehicleTable.Tiers) 49 | { 50 | river.writeString(vehicleTier.Name); 51 | river.writeSingle(vehicleTier.Chance); 52 | river.writeByte(vehicleTier.SpawnsCount); 53 | 54 | foreach (VehicleSpawnData vehicleSpawn in vehicleTier.Spawns) 55 | { 56 | river.writeUInt16(vehicleSpawn.VehicleId); 57 | } 58 | } 59 | } 60 | 61 | river.writeUInt16(SpawnpointsCount); 62 | 63 | foreach (VehicleSpawnpointData vehicleSpawnpoint in Spawnpoints) 64 | { 65 | river.writeByte(vehicleSpawnpoint.Type); 66 | river.writeSingleVector3(vehicleSpawnpoint.Point); 67 | river.writeByte(vehicleSpawnpoint.Angle); 68 | } 69 | 70 | river.closeRiver(); 71 | } 72 | 73 | public static VehiclesDataContent FromFile(string fileNamePath) 74 | { 75 | River river = new(fileNamePath); 76 | 77 | VehiclesDataContent content = new(); 78 | 79 | content.SaveDataVersion = river.readByte(); 80 | 81 | if (content.SaveDataVersion > 1 && content.SaveDataVersion < 3) 82 | { 83 | river.readSteamID(); 84 | } 85 | 86 | content.TablesCount = river.readByte(); 87 | content.Tables = new(); 88 | 89 | for (byte i = 0; i < content.TablesCount; i++) 90 | { 91 | VehicleTableData vehicleTable = new(); 92 | vehicleTable.Color = river.readColor(); 93 | vehicleTable.Name = river.readString(); 94 | 95 | if (content.SaveDataVersion > 3) 96 | { 97 | vehicleTable.TableId = river.readUInt16(); 98 | } else 99 | { 100 | vehicleTable.TableId = 0; 101 | } 102 | 103 | vehicleTable.TiersCount = river.readByte(); 104 | vehicleTable.Tiers = new(); 105 | 106 | for (byte j = 0; j < vehicleTable.TiersCount; j++) 107 | { 108 | VehicleTierData vehicleTier = new(); 109 | vehicleTier.Name = river.readString(); 110 | vehicleTier.Chance = river.readSingle(); 111 | vehicleTier.SpawnsCount = river.readByte(); 112 | vehicleTier.Spawns = new(); 113 | 114 | for (byte k = 0; k < vehicleTier.SpawnsCount; k++) 115 | { 116 | VehicleSpawnData vehicleSpawn = new(); 117 | vehicleSpawn.VehicleId = river.readUInt16(); 118 | vehicleTier.Spawns.Add(vehicleSpawn); 119 | } 120 | 121 | vehicleTable.Tiers.Add(vehicleTier); 122 | } 123 | 124 | content.Tables.Add(vehicleTable); 125 | } 126 | 127 | content.SpawnpointsCount = river.readUInt16(); 128 | content.Spawnpoints = new(); 129 | 130 | for (ushort l = 0; l < content.SpawnpointsCount; l++) 131 | { 132 | VehicleSpawnpointData vehicleSpawnpoint = new(); 133 | vehicleSpawnpoint.Type = river.readByte(); 134 | vehicleSpawnpoint.Point = river.readSingleVector3(); 135 | vehicleSpawnpoint.Angle = river.readByte(); 136 | 137 | content.Spawnpoints.Add(vehicleSpawnpoint); 138 | } 139 | 140 | river.closeRiver(); 141 | return content; 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Zombies/ZombieClothData.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Models.Contents.Zombies 2 | { 3 | public class ZombieClothData 4 | { 5 | public ushort Item { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Zombies/ZombieSlotData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UnturnedMapMergeTool.Models.Contents.Zombies 4 | { 5 | public class ZombieSlotData 6 | { 7 | public float Chance { get; set; } 8 | public byte ClothesCount { get; set; } 9 | 10 | public List Clothes { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/Zombies/ZombieTableData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnturnedMapMergeTool.Unturned.Unity; 7 | 8 | namespace UnturnedMapMergeTool.Models.Contents.Zombies 9 | { 10 | public class ZombieTableData 11 | { 12 | public Guid TableUniqueId { get; set; } 13 | public Color Color { get; set; } 14 | public string Name { get; set; } 15 | public bool IsMega { get; set; } 16 | public ushort Health { get; set; } 17 | public byte Damage { get; set; } 18 | public byte LootIndex { get; set; } 19 | public ushort LootId { get; set; } 20 | public uint XP { get; set; } 21 | public float Regen { get; set; } 22 | public string DifficultyGuid { get; set; } 23 | 24 | public byte SlotsCount { get; set; } 25 | public ZombieSlotData[] Slots { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Contents/ZombiesDataContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using UnturnedMapMergeTool.Models.Contents.Zombies; 6 | using UnturnedMapMergeTool.Unturned; 7 | 8 | namespace UnturnedMapMergeTool.Models.Contents 9 | { 10 | public class ZombiesDataContent 11 | { 12 | public ZombiesDataContent(byte saveDataVersion, byte tablesCount) 13 | { 14 | SaveDataVersion = saveDataVersion; 15 | TablesCount = tablesCount; 16 | 17 | Tables = new(); 18 | } 19 | 20 | public ZombiesDataContent() 21 | { 22 | 23 | } 24 | 25 | public byte SaveDataVersion { get; set; } 26 | public byte TablesCount { get; set; } 27 | 28 | public List Tables { get; set; } 29 | 30 | public void SaveToFile(string fileNamePath) 31 | { 32 | Block block = new(); 33 | block.writeByte(SaveDataVersion); 34 | block.writeByte(TablesCount); 35 | 36 | for (byte i = 0; i < TablesCount; i++) 37 | { 38 | ZombieTableData zombieTable = Tables[i]; 39 | block.writeColor(zombieTable.Color); 40 | block.writeString(zombieTable.Name); 41 | block.writeBoolean(zombieTable.IsMega); 42 | block.writeUInt16(zombieTable.Health); 43 | block.writeByte(zombieTable.Damage); 44 | block.writeByte(zombieTable.LootIndex); 45 | block.writeUInt16(zombieTable.LootId); 46 | block.writeUInt32(zombieTable.XP); 47 | block.writeSingle(zombieTable.Regen); 48 | block.writeString(zombieTable.DifficultyGuid); 49 | 50 | block.writeByte(zombieTable.SlotsCount); 51 | 52 | for (byte j = 0; j < zombieTable.SlotsCount; j++) 53 | { 54 | ZombieSlotData zombieSlot = zombieTable.Slots[j]; 55 | block.writeSingle(zombieSlot.Chance); 56 | 57 | block.writeByte(zombieSlot.ClothesCount); 58 | 59 | for (byte k = 0; k < zombieSlot.ClothesCount; k++) 60 | { 61 | ZombieClothData zombieCloth = zombieSlot.Clothes[k]; 62 | block.writeUInt16(zombieCloth.Item); 63 | } 64 | } 65 | } 66 | 67 | byte[] bytes = block.getBytes(out _); 68 | File.WriteAllBytes(fileNamePath, bytes); 69 | } 70 | 71 | public static ZombiesDataContent FromFile(string fileNamePath) 72 | { 73 | byte[] bytes = File.ReadAllBytes(fileNamePath); 74 | 75 | Block block = new(0, bytes); 76 | 77 | ZombiesDataContent content = new(); 78 | 79 | content.SaveDataVersion = block.readByte(); 80 | if (content.SaveDataVersion > 3 && content.SaveDataVersion < 5) 81 | { 82 | block.readSteamID(); 83 | } 84 | 85 | if (content.SaveDataVersion >= 10) 86 | { 87 | block.readInt32(); 88 | } 89 | 90 | content.Tables = new(); 91 | 92 | // TODO: Add support for SavedataVersion < 2 93 | 94 | content.TablesCount = block.readByte(); 95 | for (byte i = 0; i < content.TablesCount; i++) 96 | { 97 | ZombieTableData zombieTable = new(); 98 | content.Tables.Add(zombieTable); 99 | 100 | if (content.SaveDataVersion >= 10) 101 | { 102 | block.readInt32(); 103 | } 104 | 105 | zombieTable.Color = block.readColor(); 106 | zombieTable.Name = block.readString(); 107 | zombieTable.IsMega = block.readBoolean(); 108 | zombieTable.Health = block.readUInt16(); 109 | zombieTable.Damage = block.readByte(); 110 | zombieTable.LootIndex = block.readByte(); 111 | if (content.SaveDataVersion > 6) 112 | { 113 | zombieTable.LootId = block.readUInt16(); 114 | } 115 | else 116 | { 117 | zombieTable.LootId = 0; 118 | } 119 | 120 | if (content.SaveDataVersion > 7) 121 | { 122 | zombieTable.XP = block.readUInt32(); 123 | } 124 | else if (zombieTable.IsMega) 125 | { 126 | zombieTable.XP = 40U; 127 | } 128 | else 129 | { 130 | zombieTable.XP = 3U; 131 | } 132 | 133 | zombieTable.Regen = 10f; 134 | if (content.SaveDataVersion > 5) 135 | { 136 | zombieTable.Regen = block.readSingle(); 137 | } 138 | zombieTable.DifficultyGuid = string.Empty; 139 | if (content.SaveDataVersion > 8) 140 | { 141 | zombieTable.DifficultyGuid = block.readString(); 142 | } 143 | 144 | zombieTable.SlotsCount = block.readByte(); 145 | zombieTable.Slots = new ZombieSlotData[zombieTable.SlotsCount]; 146 | 147 | for (byte j = 0; j < zombieTable.SlotsCount; j++) 148 | { 149 | ZombieSlotData zombieSlot = new(); 150 | zombieTable.Slots[j] = zombieSlot; 151 | zombieSlot.Clothes = new List(); 152 | 153 | zombieSlot.Chance = block.readSingle(); 154 | zombieSlot.ClothesCount = block.readByte(); 155 | 156 | for (byte k = 0; k < zombieSlot.ClothesCount; k++) 157 | { 158 | ZombieClothData zombieCloth = new(); 159 | zombieCloth.Item = block.readUInt16(); 160 | zombieSlot.Clothes.Add(zombieCloth); 161 | } 162 | } 163 | } 164 | 165 | return content; 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Coordinate.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Models 2 | { 3 | public class Coordinate 4 | { 5 | public int X { get; set; } 6 | public int Y { get; set; } 7 | 8 | public override string ToString() 9 | { 10 | return $"[X: {X}, Y: {Y}]"; 11 | } 12 | 13 | public override bool Equals(object obj) 14 | { 15 | if (obj is Coordinate coordinate) 16 | { 17 | return X == coordinate.X && Y == coordinate.Y; 18 | } 19 | 20 | return false; 21 | } 22 | 23 | public override int GetHashCode() 24 | { 25 | return X.GetHashCode() ^ Y.GetHashCode(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/CopyMapData.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Services; 2 | 3 | namespace UnturnedMapMergeTool.Models 4 | { 5 | public class CopyMapData where T : class 6 | { 7 | public CopyMap CopyMap { get; set; } 8 | public T Content { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Enums/EMapSize.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Models.Enums 2 | { 3 | public enum EMapSize 4 | { 5 | Medium, 6 | Insane, 7 | Large, 8 | Small, 9 | Tiny 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/Enums/ETileType.cs: -------------------------------------------------------------------------------- 1 | namespace UnturnedMapMergeTool.Models.Enums 2 | { 3 | public enum ETileType 4 | { 5 | Heightmap, 6 | Splatmap, 7 | Hole 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Models/TileFileInfo.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Extensions; 2 | using UnturnedMapMergeTool.Models.Enums; 3 | 4 | namespace UnturnedMapMergeTool.Models 5 | { 6 | public class TileFileInfo 7 | { 8 | public int OriginalTileX { get; set; } 9 | public int OriginalTileY { get; set; } 10 | 11 | public string OriginalFileName { get; set; } 12 | public string FileNameFormat { get; set; } 13 | 14 | public static TileFileInfo FromFileName(string fileName, ETileType tileType) 15 | { 16 | string str = fileName.Substring(5, fileName.Length - 5); 17 | string[] arr = str.Split('_'); 18 | 19 | int x = int.Parse(arr[0]); 20 | int y = int.Parse(arr[1].TrimEnd(".bin")); 21 | 22 | arr[0] = "{0}"; 23 | arr[1] = "{1}"; 24 | 25 | string strFormat = string.Join('_', arr); 26 | if (tileType == ETileType.Hole) 27 | { 28 | strFormat += ".bin"; 29 | } 30 | string fileNameFormat = fileName.Substring(0, 5) + strFormat; 31 | 32 | return new TileFileInfo() 33 | { 34 | OriginalTileX = x, 35 | OriginalTileY = y, 36 | FileNameFormat = fileNameFormat, 37 | OriginalFileName = fileName 38 | }; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Program.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using UnturnedMapMergeTool; 7 | using UnturnedMapMergeTool.DataMergeTools; 8 | using UnturnedMapMergeTool.DataMergeTools.Spawns; 9 | using UnturnedMapMergeTool.Models.Configs; 10 | using UnturnedMapMergeTool.Services; 11 | 12 | internal class Program 13 | { 14 | 15 | private static void Main(string[] args) 16 | { 17 | Log.Logger = new LoggerConfiguration() 18 | .WriteTo.Console() 19 | .WriteTo.File("log.txt") 20 | .CreateLogger(); 21 | 22 | Log.Information($"UnturnedMapMergeTool v{typeof(Program).Assembly.GetName().Version} has been loaded!"); 23 | 24 | Config config; 25 | if (File.Exists("config.json")) 26 | { 27 | string configJson = File.ReadAllText("config.json"); 28 | config = JsonConvert.DeserializeObject(configJson); 29 | } 30 | else 31 | { 32 | config = new(); 33 | config.LoadDefaultValues(); 34 | 35 | string configJson = JsonConvert.SerializeObject(config, Formatting.Indented); 36 | File.WriteAllText("config.json", configJson); 37 | Log.Information("Generated a config.json file with. Modify it before running this program again!"); 38 | return; 39 | } 40 | 41 | try 42 | { 43 | Start(config); 44 | } catch (Exception e) 45 | { 46 | Log.Error(e, ""); 47 | } 48 | 49 | Log.Information("Press any key to exit the program..."); 50 | Console.ReadKey(); 51 | } 52 | 53 | private static void Start(Config config) 54 | { 55 | OutputMap outputMap = new(config.OutputMap); 56 | 57 | // Delete existing directories and create empty 58 | outputMap.Preapare(); 59 | 60 | List copyMaps = new(); 61 | 62 | ObjectsDataMergeTool objectsDataMergeTool = new(); 63 | BuildablesDataMergeTool buildablesDataMergeTool = new(); 64 | TreesDataMergeTool treesDataMergeTool = new(); 65 | RoadsDataMergeTool roadsDataMergeTool = new(); 66 | PathsDataMergeTool pathsDataMergeTool = new(); 67 | NodesDataMergeTool nodesDataMergeTool = new(); 68 | BoundsDataMergeTool boundsDataMergeTool = new(); 69 | FlagsDataMergeTool flagsDataMergeTool = new(); 70 | //NavigationsDataMergeTool navigationsDataMergeTool = new(); 71 | 72 | ZombiesDataMergeTool zombiesDataMergeTool = new(); 73 | AnimalsDataMergeTool animalsDataMergeTool = new(); 74 | PlayersDataMergeTool playersDataMergeTool = new(); 75 | FaunaDataMergeTool faunaDataMergeTool = new(); 76 | VehiclesDataMergeTool vehiclesDataMergeTool = new(); 77 | ItemsDataMergeTool itemsDataMergeTool = new(); 78 | JarsDataMergeTool jarsDataMergeTool = new(); 79 | 80 | Log.Information($"Start combining {config.Maps.Count} maps"); 81 | 82 | foreach (CopyMapConfig mapConfig in config.Maps) 83 | { 84 | CopyMap copyMap = new(mapConfig, outputMap); 85 | 86 | objectsDataMergeTool.ReadData(copyMap); 87 | buildablesDataMergeTool.ReadData(copyMap); 88 | treesDataMergeTool.ReadData(copyMap); 89 | 90 | roadsDataMergeTool.ReadData(copyMap); 91 | pathsDataMergeTool.ReadData(copyMap); 92 | nodesDataMergeTool.ReadData(copyMap); 93 | boundsDataMergeTool.ReadData(copyMap); 94 | flagsDataMergeTool.ReadData(copyMap); 95 | //navigationsDataMergeTool.ReadData(copyMap); 96 | 97 | zombiesDataMergeTool.ReadData(copyMap); 98 | animalsDataMergeTool.ReadData(copyMap); 99 | playersDataMergeTool.ReadData(copyMap); 100 | faunaDataMergeTool.ReadData(copyMap); 101 | vehiclesDataMergeTool.ReadData(copyMap); 102 | itemsDataMergeTool.ReadData(copyMap); 103 | jarsDataMergeTool.ReadData(copyMap); 104 | 105 | copyMaps.Add(copyMap); 106 | 107 | copyMap.CopyAllTiles(); 108 | } 109 | 110 | objectsDataMergeTool.CombineAndSaveData(outputMap); 111 | buildablesDataMergeTool.CombineAndSaveData(outputMap); 112 | treesDataMergeTool.CombineAndSaveData(outputMap); 113 | roadsDataMergeTool.CombineAndSaveData(outputMap); 114 | pathsDataMergeTool.CombineAndSaveData(outputMap); 115 | nodesDataMergeTool.CombineAndSaveData(outputMap); 116 | boundsDataMergeTool.CombineAndSaveData(outputMap); 117 | flagsDataMergeTool.CombineAndSaveData(outputMap); 118 | //navigationsDataMergeTool.CombineAndSaveData(outputMap); 119 | 120 | zombiesDataMergeTool.CombineAndSaveData(outputMap); 121 | animalsDataMergeTool.CombineAndSaveData(outputMap); 122 | playersDataMergeTool.CombineAndSaveData(outputMap); 123 | faunaDataMergeTool.CombineAndSaveData(outputMap); 124 | vehiclesDataMergeTool.CombineAndSaveData(outputMap); 125 | itemsDataMergeTool.CombineAndSaveData(outputMap); 126 | jarsDataMergeTool.CombineAndSaveData(outputMap); 127 | 128 | Log.Information($"Finished migrating {config.Maps.Count} maps!"); 129 | } 130 | } -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Services/CopyMap.Logs.cs: -------------------------------------------------------------------------------- 1 | using Serilog; 2 | using UnturnedMapMergeTool.Models.Enums; 3 | 4 | namespace UnturnedMapMergeTool.Services 5 | { 6 | public partial class CopyMap 7 | { 8 | private void LogTile(ETileType tileType, string message) 9 | { 10 | LogInformation($"[{tileType}] {message}"); 11 | } 12 | 13 | private void LogTileWarning(ETileType tileType, string message) 14 | { 15 | LogWarning($"[{tileType}] {message}"); 16 | } 17 | 18 | private void LogInformation(string message) 19 | { 20 | Log.Information($"[{config.Name}]: {message}"); 21 | } 22 | 23 | private void LogWarning(string message) 24 | { 25 | Log.Warning($"[{config.Name}]: {message}"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Services/CopyMap.Tiles.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using UnturnedMapMergeTool.Helpers; 4 | using UnturnedMapMergeTool.Models; 5 | using UnturnedMapMergeTool.Models.Enums; 6 | 7 | namespace UnturnedMapMergeTool.Services 8 | { 9 | public partial class CopyMap 10 | { 11 | public void CopyAllTiles() 12 | { 13 | CopyTilesFromDirectory("Landscape/Heightmaps", ETileType.Heightmap); 14 | CopyTilesFromDirectory("Landscape/Splatmaps", ETileType.Splatmap); 15 | CopyTilesFromDirectory("Landscape/Holes", ETileType.Hole); 16 | } 17 | 18 | private void CopyTilesFromDirectory(string directory, ETileType tileType) 19 | { 20 | string directoryPath = Path.Combine(config.Path, directory); 21 | 22 | if (!Directory.Exists(directoryPath)) 23 | { 24 | LogTile(tileType, $"No {tileType} tiles on this map"); 25 | return; 26 | } 27 | 28 | string outputDirectoryPath = outputMap.CombinePath(directory); 29 | 30 | foreach (string fileNamePath in Directory.EnumerateFiles(directoryPath)) 31 | { 32 | string fileName = Path.GetFileName(fileNamePath); 33 | TileFileInfo fileInfo = TileFileInfo.FromFileName(fileName, tileType); 34 | 35 | if (!config.WithBorders && TilesHelper.IsBorder(fileInfo.OriginalTileX, fileInfo.OriginalTileY, config.Size)) 36 | { 37 | LogTile(tileType, $"Skipping border tile {fileName}"); 38 | continue; 39 | } 40 | 41 | Coordinate originalCoordinate = new() 42 | { 43 | X = TilesHelper.TileToIndex(fileInfo.OriginalTileX, config.Size), 44 | Y = TilesHelper.TileToIndex(fileInfo.OriginalTileY, config.Size) 45 | }; 46 | 47 | if (config.BypassTiles != null && config.BypassTiles.Length > 0) 48 | { 49 | if (config.BypassTiles.Contains(originalCoordinate)) 50 | { 51 | LogTileWarning(tileType, $"The tile {originalCoordinate} was on the bypass list"); 52 | continue; 53 | } 54 | } 55 | 56 | Coordinate targetCoordinate = new() 57 | { 58 | X = originalCoordinate.X + StartCoordinate.X, 59 | Y = originalCoordinate.Y + StartCoordinate.Y 60 | }; 61 | 62 | int targetTileX = TilesHelper.IndexToTile(targetCoordinate.X, outputMap.Config.Size); 63 | int targetTileY = TilesHelper.IndexToTile(targetCoordinate.Y, outputMap.Config.Size); 64 | 65 | string targetFileName = string.Format(fileInfo.FileNameFormat, targetTileX, targetTileY); 66 | string targetFileNamePath = Path.Combine(outputDirectoryPath, targetFileName); 67 | 68 | bool flag = File.Exists(targetFileNamePath); 69 | File.Copy(fileNamePath, targetFileNamePath, true); 70 | if (flag) 71 | { 72 | LogTile(tileType, $"Overrided {targetFileName} with {fileName}"); 73 | } 74 | else 75 | { 76 | LogTile(tileType, $"Copied {fileName} to {targetFileName}"); 77 | } 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Services/CopyMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnturnedMapMergeTool.Helpers; 4 | using UnturnedMapMergeTool.Models; 5 | using UnturnedMapMergeTool.Models.Configs; 6 | using UnturnedMapMergeTool.Models.Contents.Flags; 7 | using UnturnedMapMergeTool.Models.Enums; 8 | using UnturnedMapMergeTool.Unturned.Unity; 9 | 10 | namespace UnturnedMapMergeTool.Services 11 | { 12 | public partial class CopyMap 13 | { 14 | private readonly CopyMapConfig config; 15 | private readonly OutputMap outputMap; 16 | 17 | public Guid Identifier { get; private set; } 18 | 19 | public CopyMap(CopyMapConfig config, OutputMap outputMap) 20 | { 21 | Identifier = Guid.NewGuid(); 22 | this.config = config; 23 | this.outputMap = outputMap; 24 | } 25 | 26 | public CopyMapConfig Config => config; 27 | 28 | private Coordinate StartCoordinate => config.StartCoordinate; 29 | 30 | public bool IsOriginalPositionBypassed(Vector3 position) 31 | { 32 | if (!ShouldIncludePosition(position)) 33 | { 34 | return true; 35 | } 36 | 37 | if (config.BypassTiles == null) 38 | { 39 | return false; 40 | } 41 | 42 | foreach (Coordinate coordinate in config.BypassTiles) 43 | { 44 | int shiftX = TilesHelper.TileToShift(coordinate.X, config.Size); 45 | int shiftY = TilesHelper.TileToShift(coordinate.Y, config.Size); 46 | int xMin = shiftX * 1024; 47 | int xMax = (shiftX + 1) * 1024; 48 | int yMin = shiftY * 1024; 49 | int yMax = (shiftY + 1) * 1024; 50 | 51 | if ((xMin <= position.x && xMax >= position.x) && (yMin <= position.z && yMax >= position.z)) 52 | { 53 | return true; 54 | } 55 | } 56 | 57 | return false; 58 | } 59 | 60 | public void ApplyPositionShift(Vector3 position) 61 | { 62 | position.x += Config.ShiftX; 63 | position.z += Config.ShiftY; 64 | } 65 | 66 | public byte MaterialShift { get; set; } = 0; 67 | 68 | // This doesn't work because there cannot be more than 10 materials (in the Roads.unity3d file) on one map 69 | public byte GetShiftedMaterialId(byte material) 70 | { 71 | return (byte)(material + MaterialShift); 72 | } 73 | 74 | public byte ZombieTypeShift { get; set; } = 0; 75 | 76 | public byte GetShiftedZombieType(byte zombieType) 77 | { 78 | return (byte)(zombieType + ZombieTypeShift); 79 | } 80 | 81 | public byte ItemTypeShift { get; set; } = 0; 82 | 83 | public byte GetShiftedItemType(byte itemType) 84 | { 85 | return (byte)(itemType + ItemTypeShift); 86 | } 87 | 88 | // Used and necessary for NavigationsDataMergeTool 89 | public List Flags { get; set; } 90 | public int FlagsStartIndex { get; set; } 91 | 92 | public bool ShouldIncludePosition(Vector3 position) 93 | { 94 | return config.WithBorders || !TilesHelper.IsBorder(position, config.Size); 95 | } 96 | 97 | public bool IsOutputMapBorder(Vector3 position) 98 | { 99 | return TilesHelper.IsBorder(position, outputMap.Config.Size); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Services/OutputMap.Helpers.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace UnturnedMapMergeTool.Services 5 | { 6 | public partial class OutputMap 7 | { 8 | public string CombinePath(params string[] args) 9 | { 10 | List list = new List() 11 | { 12 | config.Path 13 | }; 14 | list.AddRange(args); 15 | return Path.Combine(list.ToArray()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Services/OutputMap.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using UnturnedMapMergeTool.Models.Configs; 4 | 5 | namespace UnturnedMapMergeTool.Services 6 | { 7 | public partial class OutputMap 8 | { 9 | private readonly OutputMapConfig config; 10 | 11 | public OutputMap(OutputMapConfig config) 12 | { 13 | this.config = config; 14 | } 15 | 16 | public OutputMapConfig Config => config; 17 | 18 | public void Preapare() 19 | { 20 | PrepareLandscapes(); 21 | PrepareSpawns(); 22 | PrepareLevel(); 23 | } 24 | 25 | private void PrepareLevel() 26 | { 27 | string spawnsDirectory = CombinePath("Level"); 28 | if (Directory.Exists(spawnsDirectory)) 29 | { 30 | Directory.Delete(spawnsDirectory, true); 31 | } 32 | 33 | Directory.CreateDirectory(spawnsDirectory); 34 | } 35 | 36 | private void PrepareSpawns() 37 | { 38 | string spawnsDirectory = CombinePath("Spawns"); 39 | if (Directory.Exists(spawnsDirectory)) 40 | { 41 | Directory.Delete(spawnsDirectory, true); 42 | } 43 | 44 | Directory.CreateDirectory(spawnsDirectory); 45 | } 46 | 47 | private void PrepareLandscapes() 48 | { 49 | string landscapesPath = Path.Combine(config.Path, "Landscape"); 50 | List otherDirectories = new List() 51 | { 52 | Path.Combine(landscapesPath, "Heightmaps"), 53 | Path.Combine(landscapesPath, "Splatmaps"), 54 | Path.Combine(landscapesPath, "Holes") 55 | }; 56 | 57 | if (Directory.Exists(landscapesPath)) 58 | { 59 | Directory.Delete(landscapesPath, true); 60 | } 61 | 62 | Directory.CreateDirectory(landscapesPath); 63 | 64 | foreach (string directoryPath in otherDirectories) 65 | { 66 | if (!Directory.Exists(directoryPath)) 67 | { 68 | Directory.CreateDirectory(directoryPath); 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/GuidBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UnturnedMapMergeTool.Unturned 4 | { 5 | public class GuidBuffer 6 | { 7 | public static Guid FromBytes(byte[] bytes) 8 | { 9 | return new Guid(bytes); 10 | } 11 | 12 | public static byte[] ToBytes(Guid guid) 13 | { 14 | return guid.ToByteArray(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/Hash.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | using UnturnedMapMergeTool.Unturned.Unity; 7 | 8 | namespace UnturnedMapMergeTool.Unturned 9 | { 10 | public class Hash 11 | { 12 | // Token: 0x06004651 RID: 18001 RVA: 0x001A5B91 File Offset: 0x001A3D91 13 | public static byte[] SHA1(byte[] bytes) 14 | { 15 | 16 | return Hash.service.ComputeHash(bytes); 17 | } 18 | 19 | // Token: 0x06004652 RID: 18002 RVA: 0x001A5B9E File Offset: 0x001A3D9E 20 | public static byte[] SHA1(Stream stream) 21 | { 22 | return Hash.service.ComputeHash(stream); 23 | } 24 | 25 | // Token: 0x06004653 RID: 18003 RVA: 0x001A5BAB File Offset: 0x001A3DAB 26 | public static byte[] SHA1(string text) 27 | { 28 | return Hash.SHA1(Encoding.UTF8.GetBytes(text)); 29 | } 30 | 31 | // Token: 0x06004654 RID: 18004 RVA: 0x001A5BBD File Offset: 0x001A3DBD 32 | public static byte[] SHA1(CSteamID steamID) 33 | { 34 | return Hash.SHA1(BitConverter.GetBytes(steamID.m_SteamID)); 35 | } 36 | 37 | // Token: 0x06004655 RID: 18005 RVA: 0x001A5BD0 File Offset: 0x001A3DD0 38 | public static bool verifyHash(byte[] hash_0, byte[] hash_1) 39 | { 40 | if (hash_0.Length != 20 || hash_1.Length != 20) 41 | { 42 | return false; 43 | } 44 | for (int i = 0; i < hash_0.Length; i++) 45 | { 46 | if (hash_0[i] != hash_1[i]) 47 | { 48 | return false; 49 | } 50 | } 51 | return true; 52 | } 53 | 54 | // Token: 0x06004656 RID: 18006 RVA: 0x001A5C06 File Offset: 0x001A3E06 55 | public static byte[] combineSHA1Hashes(byte[] a, byte[] b) 56 | { 57 | if (a.Length != 20 || b.Length != 20) 58 | { 59 | throw new Exception("both lengths should be 20"); 60 | } 61 | a.CopyTo(Hash._40bytes, 0); 62 | b.CopyTo(Hash._40bytes, 20); 63 | return Hash.SHA1(Hash._40bytes); 64 | } 65 | 66 | // Token: 0x06004657 RID: 18007 RVA: 0x001A5C44 File Offset: 0x001A3E44 67 | public static byte[] combine(params byte[][] hashes) 68 | { 69 | byte[] array = new byte[hashes.Length * 20]; 70 | for (int i = 0; i < hashes.Length; i++) 71 | { 72 | hashes[i].CopyTo(array, i * 20); 73 | } 74 | return Hash.SHA1(array); 75 | } 76 | 77 | // Token: 0x06004658 RID: 18008 RVA: 0x001A5C80 File Offset: 0x001A3E80 78 | public static byte[] combine(List hashes) 79 | { 80 | byte[] array = new byte[hashes.Count * 20]; 81 | for (int i = 0; i < hashes.Count; i++) 82 | { 83 | hashes[i].CopyTo(array, i * 20); 84 | } 85 | return Hash.SHA1(array); 86 | } 87 | 88 | // Token: 0x06004659 RID: 18009 RVA: 0x001A5CC4 File Offset: 0x001A3EC4 89 | public static string toString(byte[] hash) 90 | { 91 | if (hash == null) 92 | { 93 | return "null"; 94 | } 95 | string text = ""; 96 | for (int i = 0; i < hash.Length; i++) 97 | { 98 | text += hash[i].ToString("X2"); 99 | } 100 | return text; 101 | } 102 | 103 | // Token: 0x0600465A RID: 18010 RVA: 0x001A5D08 File Offset: 0x001A3F08 104 | internal static string ToCodeString(byte[] hash) 105 | { 106 | StringBuilder stringBuilder = new StringBuilder(hash.Length * 6); 107 | stringBuilder.Append("0x"); 108 | stringBuilder.Append(hash[0].ToString("X2")); 109 | for (int i = 1; i < hash.Length; i++) 110 | { 111 | stringBuilder.Append(", 0x"); 112 | stringBuilder.Append(hash[i].ToString("X2")); 113 | } 114 | return stringBuilder.ToString(); 115 | } 116 | 117 | // Token: 0x0600465B RID: 18011 RVA: 0x001A5D7C File Offset: 0x001A3F7C 118 | public static void log(byte[] hash) 119 | { 120 | if (hash == null || hash.Length != 20) 121 | { 122 | return; 123 | } 124 | } 125 | 126 | // Token: 0x04002DF7 RID: 11767 127 | private static SHA1 service = System.Security.Cryptography.SHA1.Create(); 128 | 129 | // Token: 0x04002DF8 RID: 11768 130 | private static byte[] _40bytes = new byte[40]; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/MathfEx.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Unturned.Unity; 2 | 3 | namespace UnturnedMapMergeTool.Unturned 4 | { 5 | public class MathfEx 6 | { 7 | public static byte ClampToByte(int value) 8 | { 9 | return (byte)Mathf.Clamp(value, 0, 255); 10 | } 11 | 12 | public static ushort ClampToUShort(int value) 13 | { 14 | return (ushort)Mathf.Clamp(value, 0, 65535); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/Regions.cs: -------------------------------------------------------------------------------- 1 | using UnturnedMapMergeTool.Unturned.Unity; 2 | 3 | namespace UnturnedMapMergeTool.Unturned 4 | { 5 | public class Regions 6 | { 7 | public static readonly byte WORLD_SIZE = 64; 8 | public static readonly byte REGION_SIZE = 128; 9 | 10 | public static bool tryGetCoordinate(Vector3 point, out byte x, out byte y) 11 | { 12 | x = byte.MaxValue; 13 | y = byte.MaxValue; 14 | if (Regions.checkSafe(point)) 15 | { 16 | x = (byte)((point.x + 4096f) / (float)Regions.REGION_SIZE); 17 | y = (byte)((point.z + 4096f) / (float)Regions.REGION_SIZE); 18 | return true; 19 | } 20 | return false; 21 | } 22 | 23 | public static bool checkSafe(Vector3 point) 24 | { 25 | return point.x >= -4096f && point.z >= -4096f && point.x < 4096f && point.z < 4096f; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/River.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using UnturnedMapMergeTool.Unturned.Unity; 5 | 6 | namespace UnturnedMapMergeTool.Unturned 7 | { 8 | public class River 9 | { 10 | // Token: 0x0600238D RID: 9101 RVA: 0x0009271C File Offset: 0x0009091C 11 | public string readString() 12 | { 13 | if (this.block != null) 14 | { 15 | return this.block.readString(); 16 | } 17 | int num = (int)this.readByte(); 18 | if (num > 0) 19 | { 20 | this.stream.Read(River.buffer, 0, num); 21 | return Encoding.UTF8.GetString(River.buffer, 0, num); 22 | } 23 | return string.Empty; 24 | } 25 | 26 | // Token: 0x0600238E RID: 9102 RVA: 0x00092772 File Offset: 0x00090972 27 | public bool readBoolean() 28 | { 29 | if (this.block != null) 30 | { 31 | return this.block.readBoolean(); 32 | } 33 | return this.readByte() > 0; 34 | } 35 | 36 | // Token: 0x0600238F RID: 9103 RVA: 0x00092791 File Offset: 0x00090991 37 | public byte readByte() 38 | { 39 | if (this.block != null) 40 | { 41 | return this.block.readByte(); 42 | } 43 | return MathfEx.ClampToByte(this.stream.ReadByte()); 44 | } 45 | 46 | // Token: 0x06002390 RID: 9104 RVA: 0x000927B8 File Offset: 0x000909B8 47 | public byte[] readBytes() 48 | { 49 | if (this.block != null) 50 | { 51 | return this.block.readByteArray(); 52 | } 53 | byte[] array = new byte[(int)this.readUInt16()]; 54 | this.stream.Read(array, 0, array.Length); 55 | return array; 56 | } 57 | 58 | // Token: 0x06002391 RID: 9105 RVA: 0x000927F7 File Offset: 0x000909F7 59 | public short readInt16() 60 | { 61 | if (this.block != null) 62 | { 63 | return this.block.readInt16(); 64 | } 65 | this.stream.Read(River.buffer, 0, 2); 66 | return BitConverter.ToInt16(River.buffer, 0); 67 | } 68 | 69 | // Token: 0x06002392 RID: 9106 RVA: 0x0009282B File Offset: 0x00090A2B 70 | public ushort readUInt16() 71 | { 72 | if (this.block != null) 73 | { 74 | return this.block.readUInt16(); 75 | } 76 | this.stream.Read(River.buffer, 0, 2); 77 | return BitConverter.ToUInt16(River.buffer, 0); 78 | } 79 | 80 | // Token: 0x06002393 RID: 9107 RVA: 0x0009285F File Offset: 0x00090A5F 81 | public int readInt32() 82 | { 83 | if (this.block != null) 84 | { 85 | return this.block.readInt32(); 86 | } 87 | this.stream.Read(River.buffer, 0, 4); 88 | return BitConverter.ToInt32(River.buffer, 0); 89 | } 90 | 91 | // Token: 0x06002394 RID: 9108 RVA: 0x00092893 File Offset: 0x00090A93 92 | public uint readUInt32() 93 | { 94 | if (this.block != null) 95 | { 96 | return this.block.readUInt32(); 97 | } 98 | this.stream.Read(River.buffer, 0, 4); 99 | return BitConverter.ToUInt32(River.buffer, 0); 100 | } 101 | 102 | // Token: 0x06002395 RID: 9109 RVA: 0x000928C7 File Offset: 0x00090AC7 103 | public float readSingle() 104 | { 105 | if (this.block != null) 106 | { 107 | return this.block.readSingle(); 108 | } 109 | this.stream.Read(River.buffer, 0, 4); 110 | return BitConverter.ToSingle(River.buffer, 0); 111 | } 112 | 113 | // Token: 0x06002396 RID: 9110 RVA: 0x000928FB File Offset: 0x00090AFB 114 | public long readInt64() 115 | { 116 | if (this.block != null) 117 | { 118 | return this.block.readInt64(); 119 | } 120 | this.stream.Read(River.buffer, 0, 8); 121 | return BitConverter.ToInt64(River.buffer, 0); 122 | } 123 | 124 | // Token: 0x06002397 RID: 9111 RVA: 0x0009292F File Offset: 0x00090B2F 125 | public ulong readUInt64() 126 | { 127 | if (this.block != null) 128 | { 129 | return this.block.readUInt64(); 130 | } 131 | this.stream.Read(River.buffer, 0, 8); 132 | return BitConverter.ToUInt64(River.buffer, 0); 133 | } 134 | 135 | // Token: 0x06002398 RID: 9112 RVA: 0x00092963 File Offset: 0x00090B63 136 | public CSteamID readSteamID() 137 | { 138 | return new CSteamID(this.readUInt64()); 139 | } 140 | 141 | // Token: 0x06002399 RID: 9113 RVA: 0x00092970 File Offset: 0x00090B70 142 | public Guid readGUID() 143 | { 144 | if (this.block != null) 145 | { 146 | return this.block.readGUID(); 147 | } 148 | 149 | byte[] bytes = this.readBytes(); 150 | return new Guid(bytes); 151 | 152 | //GuidBuffer guidBuffer = default(GuidBuffer); 153 | //guidBuffer.Read(this.readBytes(), 0); 154 | //return guidBuffer.GUID; 155 | } 156 | 157 | // Token: 0x0600239A RID: 9114 RVA: 0x000929AD File Offset: 0x00090BAD 158 | public Vector3 readSingleVector3() 159 | { 160 | return new Vector3(this.readSingle(), this.readSingle(), this.readSingle()); 161 | } 162 | 163 | // Token: 0x0600239B RID: 9115 RVA: 0x000929C6 File Offset: 0x00090BC6 164 | public EulerAngles readSingleQuaternion() 165 | { 166 | float x = this.readSingle(); 167 | float y = this.readSingle(); 168 | float z = this.readSingle(); 169 | return new EulerAngles(x, y, z); 170 | } 171 | 172 | // Token: 0x0600239C RID: 9116 RVA: 0x000929DF File Offset: 0x00090BDF 173 | public Color readColor() 174 | { 175 | return new Color((float)this.readByte() / 255f, (float)this.readByte() / 255f, (float)this.readByte() / 255f); 176 | } 177 | 178 | // Token: 0x0600239D RID: 9117 RVA: 0x00092A10 File Offset: 0x00090C10 179 | public void writeString(string value) 180 | { 181 | if (this.block != null) 182 | { 183 | this.block.writeString(value); 184 | return; 185 | } 186 | byte[] bytes = Encoding.UTF8.GetBytes(value); 187 | byte b = MathfEx.ClampToByte(bytes.Length); 188 | this.stream.WriteByte(b); 189 | this.stream.Write(bytes, 0, (int)b); 190 | this.water += (int)(1 + b); 191 | } 192 | 193 | // Token: 0x0600239E RID: 9118 RVA: 0x00092A71 File Offset: 0x00090C71 194 | public void writeBoolean(bool value) 195 | { 196 | if (this.block != null) 197 | { 198 | this.block.writeBoolean(value); 199 | return; 200 | } 201 | this.stream.WriteByte(value ? (byte)1 : (byte)0); 202 | this.water++; 203 | } 204 | 205 | // Token: 0x0600239F RID: 9119 RVA: 0x00092AA8 File Offset: 0x00090CA8 206 | public void writeByte(byte value) 207 | { 208 | if (this.block != null) 209 | { 210 | this.block.writeByte(value); 211 | return; 212 | } 213 | this.stream.WriteByte(value); 214 | this.water++; 215 | } 216 | 217 | // Token: 0x060023A0 RID: 9120 RVA: 0x00092ADC File Offset: 0x00090CDC 218 | public void writeBytes(byte[] values) 219 | { 220 | if (this.block != null) 221 | { 222 | this.block.writeByteArray(values); 223 | return; 224 | } 225 | ushort num = MathfEx.ClampToUShort(values.Length); 226 | this.writeUInt16(num); 227 | this.stream.Write(values, 0, (int)num); 228 | this.water += (int)num; 229 | } 230 | 231 | // Token: 0x060023A1 RID: 9121 RVA: 0x00092B2C File Offset: 0x00090D2C 232 | public void writeInt16(short value) 233 | { 234 | if (this.block != null) 235 | { 236 | this.block.writeInt16(value); 237 | return; 238 | } 239 | byte[] bytes = BitConverter.GetBytes(value); 240 | this.stream.Write(bytes, 0, 2); 241 | this.water += 2; 242 | } 243 | 244 | // Token: 0x060023A2 RID: 9122 RVA: 0x00092B74 File Offset: 0x00090D74 245 | public void writeUInt16(ushort value) 246 | { 247 | if (this.block != null) 248 | { 249 | this.block.writeUInt16(value); 250 | return; 251 | } 252 | byte[] bytes = BitConverter.GetBytes(value); 253 | this.stream.Write(bytes, 0, 2); 254 | this.water += 2; 255 | } 256 | 257 | // Token: 0x060023A3 RID: 9123 RVA: 0x00092BBC File Offset: 0x00090DBC 258 | public void writeInt32(int value) 259 | { 260 | if (this.block != null) 261 | { 262 | this.block.writeInt32(value); 263 | return; 264 | } 265 | byte[] bytes = BitConverter.GetBytes(value); 266 | this.stream.Write(bytes, 0, 4); 267 | this.water += 4; 268 | } 269 | 270 | // Token: 0x060023A4 RID: 9124 RVA: 0x00092C04 File Offset: 0x00090E04 271 | public void writeUInt32(uint value) 272 | { 273 | if (this.block != null) 274 | { 275 | this.block.writeUInt32(value); 276 | return; 277 | } 278 | byte[] bytes = BitConverter.GetBytes(value); 279 | this.stream.Write(bytes, 0, 4); 280 | this.water += 4; 281 | } 282 | 283 | // Token: 0x060023A5 RID: 9125 RVA: 0x00092C4C File Offset: 0x00090E4C 284 | public void writeSingle(float value) 285 | { 286 | if (this.block != null) 287 | { 288 | this.block.writeSingle(value); 289 | return; 290 | } 291 | byte[] bytes = BitConverter.GetBytes(value); 292 | this.stream.Write(bytes, 0, 4); 293 | this.water += 4; 294 | } 295 | 296 | // Token: 0x060023A6 RID: 9126 RVA: 0x00092C94 File Offset: 0x00090E94 297 | public void writeInt64(long value) 298 | { 299 | if (this.block != null) 300 | { 301 | this.block.writeInt64(value); 302 | return; 303 | } 304 | byte[] bytes = BitConverter.GetBytes(value); 305 | this.stream.Write(bytes, 0, 8); 306 | this.water += 8; 307 | } 308 | 309 | // Token: 0x060023A7 RID: 9127 RVA: 0x00092CDC File Offset: 0x00090EDC 310 | public void writeUInt64(ulong value) 311 | { 312 | if (this.block != null) 313 | { 314 | this.block.writeUInt64(value); 315 | return; 316 | } 317 | byte[] bytes = BitConverter.GetBytes(value); 318 | this.stream.Write(bytes, 0, 8); 319 | this.water += 8; 320 | } 321 | 322 | // Token: 0x060023A8 RID: 9128 RVA: 0x00092D21 File Offset: 0x00090F21 323 | public void writeSteamID(CSteamID steamID) 324 | { 325 | this.writeUInt64(steamID.m_SteamID); 326 | } 327 | 328 | // Token: 0x060023A9 RID: 9129 RVA: 0x00092D30 File Offset: 0x00090F30 329 | public void writeGUID(Guid guid) 330 | { 331 | //GuidBuffer guidBuffer = new GuidBuffer(guid); 332 | //guidBuffer.Write(GuidBuffer.GUID_BUFFER, 0); 333 | this.writeBytes(guid.ToByteArray()); 334 | } 335 | 336 | // Token: 0x060023AA RID: 9130 RVA: 0x00092D5D File Offset: 0x00090F5D 337 | public void writeSingleVector3(Vector3 value) 338 | { 339 | this.writeSingle(value.x); 340 | this.writeSingle(value.y); 341 | this.writeSingle(value.z); 342 | } 343 | 344 | // Token: 0x060023AB RID: 9131 RVA: 0x00092D84 File Offset: 0x00090F84 345 | public void writeSingleQuaternion(EulerAngles value) 346 | { 347 | this.writeSingle(value.x); 348 | this.writeSingle(value.y); 349 | this.writeSingle(value.z); 350 | } 351 | 352 | // Token: 0x060023AC RID: 9132 RVA: 0x00092DBD File Offset: 0x00090FBD 353 | public void writeColor(Color value) 354 | { 355 | this.writeByte((byte)(value.r * 255f)); 356 | this.writeByte((byte)(value.g * 255f)); 357 | this.writeByte((byte)(value.b * 255f)); 358 | } 359 | 360 | // Token: 0x060023AD RID: 9133 RVA: 0x00092DF8 File Offset: 0x00090FF8 361 | public byte[] getHash() 362 | { 363 | this.stream.Position = 0L; 364 | return Hash.SHA1(this.stream); 365 | } 366 | 367 | // Token: 0x060023AE RID: 9134 RVA: 0x00092E14 File Offset: 0x00091014 368 | public void closeRiver() 369 | { 370 | if (this.block != null) 371 | { 372 | byte[] bytes = block.getBytes(out int size); 373 | File.WriteAllBytes(path, bytes); 374 | return; 375 | } 376 | if (this.water > 0) 377 | { 378 | this.stream.SetLength((long)this.water); 379 | } 380 | this.stream.Flush(); 381 | this.stream.Close(); 382 | this.stream.Dispose(); 383 | } 384 | 385 | // Token: 0x060023AF RID: 9135 RVA: 0x00092E78 File Offset: 0x00091078 386 | public River(string newPath) 387 | { 388 | this.path = newPath; 389 | if (!Directory.Exists(Path.GetDirectoryName(this.path))) 390 | { 391 | Directory.CreateDirectory(Path.GetDirectoryName(this.path)); 392 | } 393 | this.stream = new FileStream(this.path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); 394 | this.water = 0; 395 | } 396 | 397 | // Token: 0x040010B8 RID: 4280 398 | private static byte[] buffer = new byte[Block.BUFFER_SIZE]; 399 | 400 | // Token: 0x040010B9 RID: 4281 401 | private int water; 402 | 403 | // Token: 0x040010BA RID: 4282 404 | private string path; 405 | 406 | // Token: 0x040010BB RID: 4283 407 | private Stream stream; 408 | 409 | // Token: 0x040010BC RID: 4284 410 | private Block block; 411 | } 412 | } 413 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/Types.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnturnedMapMergeTool.Unturned.Unity; 3 | 4 | namespace UnturnedMapMergeTool.Unturned 5 | { 6 | public class Types 7 | { 8 | // Token: 0x0400223B RID: 8763 9 | public static readonly Type STRING_TYPE = typeof(string); 10 | 11 | // Token: 0x0400223C RID: 8764 12 | public static readonly Type STRING_ARRAY_TYPE = typeof(string[]); 13 | 14 | // Token: 0x0400223D RID: 8765 15 | public static readonly Type BOOLEAN_TYPE = typeof(bool); 16 | 17 | // Token: 0x0400223E RID: 8766 18 | public static readonly Type BOOLEAN_ARRAY_TYPE = typeof(bool[]); 19 | 20 | // Token: 0x0400223F RID: 8767 21 | public static readonly Type BYTE_ARRAY_TYPE = typeof(byte[]); 22 | 23 | // Token: 0x04002240 RID: 8768 24 | public static readonly Type BYTE_TYPE = typeof(byte); 25 | 26 | // Token: 0x04002241 RID: 8769 27 | public static readonly Type INT16_TYPE = typeof(short); 28 | 29 | // Token: 0x04002242 RID: 8770 30 | public static readonly Type UINT16_TYPE = typeof(ushort); 31 | 32 | // Token: 0x04002243 RID: 8771 33 | public static readonly Type INT32_ARRAY_TYPE = typeof(int[]); 34 | 35 | // Token: 0x04002244 RID: 8772 36 | public static readonly Type INT32_TYPE = typeof(int); 37 | 38 | // Token: 0x04002245 RID: 8773 39 | public static readonly Type UINT32_TYPE = typeof(uint); 40 | 41 | // Token: 0x04002246 RID: 8774 42 | public static readonly Type SINGLE_TYPE = typeof(float); 43 | 44 | // Token: 0x04002247 RID: 8775 45 | public static readonly Type INT64_TYPE = typeof(long); 46 | 47 | // Token: 0x04002248 RID: 8776 48 | public static readonly Type UINT64_ARRAY_TYPE = typeof(ulong[]); 49 | 50 | // Token: 0x04002249 RID: 8777 51 | public static readonly Type UINT64_TYPE = typeof(ulong); 52 | 53 | // Token: 0x0400224A RID: 8778 54 | public static readonly Type STEAM_ID_TYPE = typeof(CSteamID); 55 | 56 | // Token: 0x0400224B RID: 8779 57 | public static readonly Type GUID_TYPE = typeof(Guid); 58 | 59 | // Token: 0x0400224C RID: 8780 60 | public static readonly Type VECTOR3_TYPE = typeof(Vector3); 61 | 62 | // Token: 0x0400224D RID: 8781 63 | public static readonly Type COLOR_TYPE = typeof(Color); 64 | 65 | // Token: 0x0400224E RID: 8782 66 | public static readonly Type QUATERNION_TYPE = typeof(EulerAngles); 67 | 68 | // Token: 0x0400224F RID: 8783 69 | public static readonly byte[] SHIFTS = new byte[] 70 | { 71 | 1, 72 | 2, 73 | 4, 74 | 8, 75 | 16, 76 | 32, 77 | 64, 78 | 128 79 | }; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/Unity/CSteamID.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Unturned.Unity 8 | { 9 | public class CSteamID 10 | { 11 | public ulong m_SteamID { get; set; } 12 | 13 | public CSteamID(ulong steamID) 14 | { 15 | m_SteamID = steamID; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/Unity/Color.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Unturned.Unity 8 | { 9 | public class Color 10 | { 11 | public Color() 12 | { 13 | 14 | } 15 | 16 | public Color(float r, float g, float b) 17 | { 18 | this.r = r; 19 | this.g = g; 20 | this.b = b; 21 | } 22 | 23 | public float r { get; set; } 24 | public float g { get; set; } 25 | public float b { get; set; } 26 | 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/Unity/EulerAngles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UnturnedMapMergeTool.Unturned.Unity 4 | { 5 | public class EulerAngles 6 | { 7 | public EulerAngles() 8 | { 9 | 10 | } 11 | 12 | public EulerAngles(float x, float y, float z) 13 | { 14 | this.x = x; 15 | this.y = y; 16 | this.z = z; 17 | } 18 | 19 | public float x { get; set; } 20 | public float y { get; set; } 21 | public float z { get; set; } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/Unity/Mathf.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UnturnedMapMergeTool.Unturned.Unity 4 | { 5 | public class Mathf 6 | { 7 | public static int CeilToInt(float f) 8 | { 9 | return (int)Math.Ceiling(f); 10 | } 11 | 12 | public static int Clamp(int value, int min, int max) 13 | { 14 | if (value < min) 15 | { 16 | value = min; 17 | } 18 | else if (value > max) 19 | { 20 | value = max; 21 | } 22 | 23 | return value; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/Unturned/Unity/Vector3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace UnturnedMapMergeTool.Unturned.Unity 8 | { 9 | public class Vector3 10 | { 11 | public Vector3() 12 | { 13 | 14 | } 15 | public Vector3(float x, float y, float z) 16 | { 17 | this.x = x; 18 | this.y = y; 19 | this.z = z; 20 | } 21 | 22 | public float x { get; set; } 23 | public float y { get; set; } 24 | public float z { get; set; } 25 | 26 | public static Vector3 one => new Vector3(1, 1, 1); 27 | 28 | public override string ToString() 29 | { 30 | return $"[x: {x}, y: {y}, z: {z}]"; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/UnturnedMapMergeTool.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | 0.4.2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Always 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /UnturnedMapMergeTool/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Maps": [ 3 | { 4 | "Name": "PEI", 5 | "Path": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Unturned\\Maps\\PEI", 6 | "Size": "Medium", 7 | "WithBorders": false, 8 | "StartCoordinate": { 9 | "X": 1, 10 | "Y": 0 11 | }, 12 | "ShiftX": 0, 13 | "ShiftY": -1024, 14 | "IgnoreAirdropNodes": false, 15 | "IgnoreArenaNodes": false, 16 | "BypassTiles": [] 17 | }, 18 | { 19 | "Name": "Washington", 20 | "Path": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Unturned\\Maps\\Washington", 21 | "Size": "Medium", 22 | "WithBorders": false, 23 | "StartCoordinate": { 24 | "X": 0, 25 | "Y": 2 26 | }, 27 | "ShiftX": -1024, 28 | "ShiftY": 1024, 29 | "IgnoreAirdropNodes": false, 30 | "IgnoreArenaNodes": false, 31 | "BypassTiles": [] 32 | }, 33 | { 34 | "Name": "Yukon", 35 | "Path": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Unturned\\Maps\\Yukon", 36 | "Size": "Medium", 37 | "WithBorders": false, 38 | "StartCoordinate": { 39 | "X": 2, 40 | "Y": 2 41 | }, 42 | "ShiftX": 1024, 43 | "ShiftY": 1024, 44 | "IgnoreAirdropNodes": false, 45 | "IgnoreArenaNodes": false, 46 | "BypassTiles": [] 47 | } 48 | ], 49 | "OutputMap": { 50 | "Path": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Unturned\\Maps\\MergedMaps", 51 | "Size": "Large" 52 | } 53 | } --------------------------------------------------------------------------------