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);
- }
- }
-}