From 07751654b799205f3e1c4074fe68976d721075c8 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Mon, 25 Jan 2021 11:05:52 -0800 Subject: [PATCH] fix(core): Moves map definitions and cleans up loading maps, regions, and tiles (#431) - [X] Moves map definitions to a `map-definitions.json` file. - [X] Creates a TileMatrixLoader. - [X] Moves tile matrix and multi data configurations closer to their classes. --- Distribution/Data/map-definitions.json | 72 ++++++++++ Projects/Server/Json/JsonConfig.cs | 1 + Projects/Server/Main.cs | 7 +- Projects/Server/{ => Maps}/Map.cs | 0 Projects/Server/Maps/MapLoader.cs | 135 ++++++++++++++++++ Projects/Server/MultiData.cs | 6 + Projects/Server/Regions/RegionLoader.cs | 19 +-- .../Server/{ => TileMatrix}/TileMatrix.cs | 0 .../Server/TileMatrix/TileMatrixLoader.cs | 56 ++++++++ .../{ => TileMatrix}/TileMatrixPatch.cs | 11 +- Projects/UOContent/Misc/MapDefinitions.cs | 59 -------- 11 files changed, 290 insertions(+), 76 deletions(-) create mode 100644 Distribution/Data/map-definitions.json rename Projects/Server/{ => Maps}/Map.cs (100%) create mode 100644 Projects/Server/Maps/MapLoader.cs rename Projects/Server/{ => TileMatrix}/TileMatrix.cs (100%) create mode 100644 Projects/Server/TileMatrix/TileMatrixLoader.cs rename Projects/Server/{ => TileMatrix}/TileMatrixPatch.cs (93%) delete mode 100644 Projects/UOContent/Misc/MapDefinitions.cs diff --git a/Distribution/Data/map-definitions.json b/Distribution/Data/map-definitions.json new file mode 100644 index 000000000..fa7a39e52 --- /dev/null +++ b/Distribution/Data/map-definitions.json @@ -0,0 +1,72 @@ +[ + { + "index": 0, + "id": 0, + "fileIndex": 0, + "name": "Felucca", + "width": 7168, + "height": 4096, + "season": 4, + "rules": "FeluccaRules" + }, + { + "index": 1, + "id": 1, + "fileIndex": 1, + "name": "Trammel", + "width": 7168, + "height": 4096, + "season": 0, + "rules": "TrammelRules" + }, + { + "index": 2, + "id": 2, + "fileIndex": 2, + "name": "Ilshenar", + "width": 2304, + "height": 1600, + "season": 1, + "rules": "TrammelRules" + }, + { + "index": 3, + "id": 3, + "fileIndex": 3, + "name": "Malas", + "width": 2560, + "height": 2048, + "season": 1, + "rules": "TrammelRules" + }, + { + "index": 4, + "id": 4, + "fileIndex": 4, + "name": "Tokuno", + "width": 1448, + "height": 1448, + "season": 1, + "rules": "TrammelRules" + }, + { + "index": 5, + "id": 5, + "fileIndex": 5, + "name": "TerMur", + "width": 1280, + "height": 4096, + "season": 1, + "rules": "TrammelRules" + }, + { + "index": 127, + "id": 127, + "fileIndex": 127, + "name": "Internal", + "width": -1, + "height": -1, + "season": 0, + "rules": "Internal" + } +] diff --git a/Projects/Server/Json/JsonConfig.cs b/Projects/Server/Json/JsonConfig.cs index 828779441..7e2df04d1 100644 --- a/Projects/Server/Json/JsonConfig.cs +++ b/Projects/Server/Json/JsonConfig.cs @@ -39,6 +39,7 @@ namespace Server.Json Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; + options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(new MapConverterFactory()); options.Converters.Add(new Point3DConverterFactory()); options.Converters.Add(new Rectangle3DConverterFactory()); diff --git a/Projects/Server/Main.cs b/Projects/Server/Main.cs index bae492e7a..90c56339e 100644 --- a/Projects/Server/Main.cs +++ b/Projects/Server/Main.cs @@ -471,8 +471,10 @@ namespace Server VerifySerialization(); + MapLoader.LoadMaps(); AssemblyHandler.Invoke("Configure"); + TileMatrixLoader.LoadTileMatrix(); RegionLoader.LoadRegions(); World.Load(); @@ -480,11 +482,6 @@ namespace Server timerThread.Start(); - foreach (var m in Map.AllMaps) - { - m.Tiles.Force(); - } - TcpServer.Start(); EventSink.InvokeServerStarted(); RunEventLoop(); diff --git a/Projects/Server/Map.cs b/Projects/Server/Maps/Map.cs similarity index 100% rename from Projects/Server/Map.cs rename to Projects/Server/Maps/Map.cs diff --git a/Projects/Server/Maps/MapLoader.cs b/Projects/Server/Maps/MapLoader.cs new file mode 100644 index 000000000..ad93b00f6 --- /dev/null +++ b/Projects/Server/Maps/MapLoader.cs @@ -0,0 +1,135 @@ +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2021 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: MapLoader.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text.Json.Serialization; +using Server.Json; + +namespace Server +{ + internal static class MapLoader + { + /* Here we configure all maps. Some notes: + * + * 1) The first 32 maps are reserved for core use. + * 2) Map 127 is reserved for core use. + * 3) Map 255 is reserved for core use. + * 4) Changing or removing any predefined maps may cause server instability. + * + * Map definitions are modified in Data/map-definitions.json: + * - : An unreserved unique index for this map + * - : An identification number used in client communications. For any visible maps, this value must be from 0-5 + * - : A file identification number. For any visible maps, this value must be from 0-5 + * - , : Size of the map (in tiles) + * - : Season of the map. 0 = Spring, 1 = Summer, 2 = Fall, 3 = Winter, 4 = Desolation + * - : Reference name for the map, used in props gump, get/set commands, region loading, etc + * - : Rules and restrictions associated with the map. See documentation for details + */ + internal static void LoadMaps() + { + var failures = new List(); + var count = 0; + + var path = Path.Combine(Core.BaseDirectory, "Data/map-definitions.json"); + + Console.Write("Map Definitions: Loading..."); + + var stopwatch = Stopwatch.StartNew(); + var maps = JsonConfig.Deserialize>(path); + + foreach (var def in maps) + { + try + { + RegisterMap(def); + count++; + } + catch (Exception ex) + { +#if DEBUG + Console.WriteLine(ex); +#endif + failures.Add($"\tInvalid map definition {def.Name} ({def.Id})"); + } + } + + stopwatch.Stop(); + + Utility.PushColor(failures.Count > 0 ? ConsoleColor.Yellow : ConsoleColor.Green); + Console.Write(failures.Count > 0 ? "done with failures" : "done"); + Utility.PopColor(); + Console.WriteLine( + " ({0} maps, {1} failures) ({2:F2} seconds)", + count, + failures.Count, + stopwatch.Elapsed.TotalSeconds + ); + + if (failures.Count > 0) + { + Utility.PushColor(ConsoleColor.Red); + Console.WriteLine(string.Join(Environment.NewLine, failures)); + Utility.PopColor(); + } + } + + private static void RegisterMap(MapDefinition mapDefinition) + { + var newMap = new Map( + mapDefinition.Id, + mapDefinition.Index, + mapDefinition.FileIndex, + Math.Max(mapDefinition.Width, Map.SectorSize), + Math.Max(mapDefinition.Height, Map.SectorSize), + mapDefinition.Season, + mapDefinition.Name, + mapDefinition.Rules + ); + + Map.Maps[mapDefinition.Index] = newMap; + Map.AllMaps.Add(newMap); + } + + internal class MapDefinition + { + [JsonPropertyName("index")] + public int Index { get; set; } + + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("fileIndex")] + public int FileIndex { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("width")] + public int Width { get; set; } + + [JsonPropertyName("height")] + public int Height { get; set; } + + [JsonPropertyName("season")] + public int Season { get; set; } + + [JsonPropertyName("rules")] + public MapRules Rules { get; set; } + } + } +} diff --git a/Projects/Server/MultiData.cs b/Projects/Server/MultiData.cs index a2ab98598..6bda94398 100644 --- a/Projects/Server/MultiData.cs +++ b/Projects/Server/MultiData.cs @@ -536,6 +536,12 @@ namespace Server List = Array.Empty(); } + public static void Configure() + { + // OSI Client Patch 7.0.9.0 + PostHSFormat = ServerConfiguration.GetOrUpdateSetting("maps.enablePostHSMultiComponentFormat", true); + } + public static bool PostHSFormat { get; set; } public Point2D Min => m_Min; diff --git a/Projects/Server/Regions/RegionLoader.cs b/Projects/Server/Regions/RegionLoader.cs index da55b5f64..06a5c87b4 100644 --- a/Projects/Server/Regions/RegionLoader.cs +++ b/Projects/Server/Regions/RegionLoader.cs @@ -22,9 +22,9 @@ using Server.Utilities; namespace Server { - public static class RegionLoader + internal static class RegionLoader { - public static void LoadRegions() + internal static void LoadRegions() { var path = Path.Join(Core.BaseDirectory, "Data/regions.json"); @@ -53,20 +53,21 @@ namespace Server stopwatch.Stop(); - Console.ForegroundColor = failures.Count > 0 ? ConsoleColor.Yellow : ConsoleColor.Green; - Console.Write("done{0}. ", failures.Count > 0 ? " with failures" : ""); - Console.ResetColor(); + Utility.PushColor(failures.Count > 0 ? ConsoleColor.Yellow : ConsoleColor.Green); + Console.Write(failures.Count > 0 ? "done with failures" : "done"); + Utility.PopColor(); Console.WriteLine( - "({0} regions, {1} failures) ({2:F2} seconds)", + " ({0} regions, {1} failures) ({2:F2} seconds)", count, failures.Count, stopwatch.Elapsed.TotalSeconds ); + if (failures.Count > 0) { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(string.Join("\n", failures)); - Console.ResetColor(); + Utility.PushColor(ConsoleColor.Red); + Console.WriteLine(string.Join(Environment.NewLine, failures)); + Utility.PopColor(); } } } diff --git a/Projects/Server/TileMatrix.cs b/Projects/Server/TileMatrix/TileMatrix.cs similarity index 100% rename from Projects/Server/TileMatrix.cs rename to Projects/Server/TileMatrix/TileMatrix.cs diff --git a/Projects/Server/TileMatrix/TileMatrixLoader.cs b/Projects/Server/TileMatrix/TileMatrixLoader.cs new file mode 100644 index 000000000..773cfc2d1 --- /dev/null +++ b/Projects/Server/TileMatrix/TileMatrixLoader.cs @@ -0,0 +1,56 @@ +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2021 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: TileMatrixLoader.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System; +using System.Diagnostics; + +namespace Server +{ + internal static class TileMatrixLoader + { + internal static void LoadTileMatrix() + { + Console.Write("Maps: Loading..."); + + var stopwatch = Stopwatch.StartNew(); + Exception exception = null; + + try + { + foreach (var m in Map.AllMaps) + { + m.Tiles.Force(); // Forces the map file stream references to load + } + } + catch (Exception ex) + { + exception = ex; + } + + stopwatch.Stop(); + + Utility.PushColor(exception != null ? ConsoleColor.Yellow : ConsoleColor.Green); + Console.Write(exception != null ? "failed" : "done"); + Utility.PopColor(); + Console.WriteLine(" ({0:F2} seconds)", stopwatch.Elapsed.TotalSeconds); + + if (exception != null) + { + Console.WriteLine(exception); + throw exception; + } + } + } +} diff --git a/Projects/Server/TileMatrixPatch.cs b/Projects/Server/TileMatrix/TileMatrixPatch.cs similarity index 93% rename from Projects/Server/TileMatrixPatch.cs rename to Projects/Server/TileMatrix/TileMatrixPatch.cs index eb2f76ce6..f406b1901 100644 --- a/Projects/Server/TileMatrixPatch.cs +++ b/Projects/Server/TileMatrix/TileMatrixPatch.cs @@ -33,8 +33,13 @@ namespace Server } } - // TODO: Use configuration - public static bool Enabled { get; set; } = true; + public static bool Enabled { get; set; } + + public static void Configure() + { + // Using this requires the old mapDif files to be present. Only needed to support Clients < 6.0.0.0 + Enabled = ServerConfiguration.GetOrUpdateSetting("maps.enableTileMatrixPatches", !Core.SE); + } public int LandBlocks { get; } @@ -143,7 +148,7 @@ namespace Server while (pCur < pEnd) { lists[pCur->m_X & 0x7][pCur->m_Y & 0x7].Add(pCur->m_ID, pCur->m_Z); - pCur = pCur + 1; + pCur += 1; } var tiles = new StaticTile[8][][]; diff --git a/Projects/UOContent/Misc/MapDefinitions.cs b/Projects/UOContent/Misc/MapDefinitions.cs deleted file mode 100644 index 3af6886fb..000000000 --- a/Projects/UOContent/Misc/MapDefinitions.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace Server.Misc -{ - public static class MapDefinitions - { - public static void Configure() - { - /* Here we configure all maps. Some notes: - * - * 1) The first 32 maps are reserved for core use. - * 2) Map 0x7F is reserved for core use. - * 3) Map 0xFF is reserved for core use. - * 4) Changing or removing any predefined maps may cause server instability. - */ - - RegisterMap(0, 0, 0, 7168, 4096, 4, "Felucca", MapRules.FeluccaRules); - RegisterMap(1, 1, 1, 7168, 4096, 0, "Trammel", MapRules.TrammelRules); - RegisterMap(2, 2, 2, 2304, 1600, 1, "Ilshenar", MapRules.TrammelRules); - RegisterMap(3, 3, 3, 2560, 2048, 1, "Malas", MapRules.TrammelRules); - RegisterMap(4, 4, 4, 1448, 1448, 1, "Tokuno", MapRules.TrammelRules); - RegisterMap(5, 5, 5, 1280, 4096, 1, "TerMur", MapRules.TrammelRules); - - RegisterMap(0x7F, 0x7F, 0x7F, Map.SectorSize, Map.SectorSize, 1, "Internal", MapRules.Internal); - - /* Example of registering a custom map: - * RegisterMap( 32, 0, 0, 6144, 4096, 3, "Iceland", MapRules.FeluccaRules ); - * - * Defined: - * RegisterMap( , , , , , , , ); - * - : An unreserved unique index for this map - * - : An identification number used in client communications. For any visible maps, this value must be from 0-5 - * - : A file identification number. For any visible maps, this value must be from 0-5 - * - , : Size of the map (in tiles) - * - : Season of the map. 0 = Spring, 1 = Summer, 2 = Fall, 3 = Winter, 4 = Desolation - * - : Reference name for the map, used in props gump, get/set commands, region loading, etc - * - : Rules and restrictions associated with the map. See documentation for details - */ - - // Using this requires the old mapDif files to be present. Only needed to support Clients < 6.0.0.0 - TileMatrixPatch.Enabled = ServerConfiguration.GetOrUpdateSetting("maps.enableTileMatrixPatches", !Core.SE); - - MultiComponentList.PostHSFormat = - ServerConfiguration.GetOrUpdateSetting( - "maps.enablePostHSMultiComponentFormat", - true - ); // OSI Client Patch 7.0.9.0 - } - - public static void RegisterMap( - int mapIndex, int mapID, int fileIndex, int width, int height, int season, - string name, MapRules rules - ) - { - var newMap = new Map(mapID, mapIndex, fileIndex, width, height, season, name, rules); - - Map.Maps[mapIndex] = newMap; - Map.AllMaps.Add(newMap); - } - } -}