From 6119774dc91311f91a447c644a84b30eeb78211e Mon Sep 17 00:00:00 2001 From: Leath Cooper Date: Fri, 4 Oct 2019 23:47:34 -0400 Subject: [PATCH] Adds support for modernuo.json (#56) --- GOALS.md | 1 + Projects/Scripts/Misc/DataPath.cs | 108 ------------------------------ Projects/Server/Configuration.cs | 73 ++++++++++++++++++++ Projects/Server/Main.cs | 21 +++--- Projects/Server/TileData.cs | 6 +- 5 files changed, 90 insertions(+), 119 deletions(-) delete mode 100644 Projects/Scripts/Misc/DataPath.cs create mode 100644 Projects/Server/Configuration.cs diff --git a/GOALS.md b/GOALS.md index 4a2a5c037..c70e89d09 100644 --- a/GOALS.md +++ b/GOALS.md @@ -4,6 +4,7 @@ - [x] Upgrade Server/Scripts to target .NET Core 3 - [X] Upgrade the code to use C# 8 standards - [X] Remove compilation of scripts at startup in favor of loading DLLs. +- [X] Support configuration via a `modernuo.json` file ### Networking - [ ] Replace Packet classes with functions diff --git a/Projects/Scripts/Misc/DataPath.cs b/Projects/Scripts/Misc/DataPath.cs deleted file mode 100644 index 7830c89f1..000000000 --- a/Projects/Scripts/Misc/DataPath.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; - -namespace Server.Misc -{ - public class DataPath - { - /* If you have not installed Ultima Online, - * or wish the server to use a separate set of datafiles, - * change the 'CustomPath' value. - * Example: - * private static string CustomPath = @"C:\Program Files\Ultima Online"; - */ - private static string CustomPath = @"C:\Ultima Online Classic"; - // private static string CustomPath = @"/Users/kamronbatman/UOC"; - - /* The following is a list of files which a required for proper execution: - * - * Multi.idx - * Multi.mul - * VerData.mul - * TileData.mul - * Map*.mul or Map*LegacyMUL.uop - * StaIdx*.mul - * Statics*.mul - * MapDif*.mul - * MapDifL*.mul - * StaDif*.mul - * StaDifL*.mul - * StaDifI*.mul - */ - - public static void Configure() - { - string pathUO = GetPath(@"Origin Worlds Online\Ultima Online\1.0", "ExePath"); - string pathTD = GetPath(@"Origin Worlds Online\Ultima Online Third Dawn\1.0", - "ExePath"); //These refer to 2D & 3D, not the Third Dawn expansion - string pathKR = GetPath(@"Origin Worlds Online\Ultima Online\KR Legacy Beta", - "ExePath"); //After KR, This is the new registry key for the 2D client - string pathSA = GetPath(@"Electronic Arts\EA Games\Ultima Online Stygian Abyss Classic", "InstallDir"); - string pathHS = GetPath(@"Electronic Arts\EA Games\Ultima Online Classic", "InstallDir"); - - if (CustomPath != null) - Core.DataDirectories.Add(CustomPath); - - if (pathUO != null) - Core.DataDirectories.Add(pathUO); - - if (pathTD != null) - Core.DataDirectories.Add(pathTD); - - if (pathKR != null) - Core.DataDirectories.Add(pathKR); - - if (pathSA != null) - Core.DataDirectories.Add(pathSA); - - if (pathHS != null) - Core.DataDirectories.Add(pathHS); - - if (Core.DataDirectories.Count == 0 && !Core.Service) - { - Console.WriteLine("Enter the Ultima Online directory:"); - Console.Write("> "); - - Core.DataDirectories.Add(Console.ReadLine()); - } - } - - private static string GetPath(string subName, string keyName) - { - return null; - /*try - { - string keyString; - - if (Core.Is64Bit) - keyString = @"SOFTWARE\Wow6432Node\{0}"; - else - keyString = @"SOFTWARE\{0}"; - - using (RegistryKey key = Registry.LocalMachine.OpenSubKey(string.Format(keyString, subName))) - { - if (key == null) - return null; - - string v = key.GetValue(keyName) as string; - - if (string.IsNullOrEmpty(v)) - return null; - - if (keyName == "InstallDir") - v = v + @"\"; - - v = Path.GetDirectoryName(v); - - if (string.IsNullOrEmpty(v)) - return null; - - return v; - } - } - catch - { - return null; - }*/ - } - } -} diff --git a/Projects/Server/Configuration.cs b/Projects/Server/Configuration.cs new file mode 100644 index 000000000..8a813cad3 --- /dev/null +++ b/Projects/Server/Configuration.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; + +namespace Server +{ + public class Configuration + { + private static Configuration m_Configuration; + + public static Configuration Instance => m_Configuration ??= ReadConfiguration(); + + public List DataDirectories { get; } = new List(); + + private static string FilePath => Path.Join(Core.BaseDirectory, "modernuo.json"); + + private static void PromptDataDirectories(Configuration config) + { + Console.WriteLine("Please enter the Ultima Online directory:"); + + string directory; + do + { + Console.Write("> "); + directory = Console.ReadLine(); + } while (!Directory.Exists(directory)); + + config.DataDirectories.Add(directory); + } + + private static Configuration ReadConfiguration() + { + Console.Write($"Reading configuration from {FilePath}..."); + Configuration config; + + if (File.Exists(FilePath)) + { + using FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read); + Span configBytes = stackalloc byte[(int)fs.Length]; + fs.Read(configBytes); + config = JsonSerializer.Deserialize(Utility.UTF8WithEncoding.GetString(configBytes)); + Console.WriteLine("done"); + } + else + { + Console.WriteLine("not found."); + config = new Configuration(); + } + + // TODO: Extend with a config read verification function that can be extended. + if (config.DataDirectories.Count == 0) + { + PromptDataDirectories(config); + config.Flush(); + } + + return config; + } + + public void Flush() + { + using FileStream fs = new FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write); + string configJson = JsonSerializer.Serialize(this, new JsonSerializerOptions {WriteIndented = true}); + Span data = stackalloc byte[Utility.UTF8WithEncoding.GetMaxByteCount(configJson.Length)]; + int bytesWritten = Utility.UTF8WithEncoding.GetBytes(configJson, data); + fs.Write(data.Slice(0, bytesWritten)); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine($"Configuration saved to {FilePath}"); + Console.ResetColor(); + } + } +} diff --git a/Projects/Server/Main.cs b/Projects/Server/Main.cs index f46b69bb2..91faa1579 100644 --- a/Projects/Server/Main.cs +++ b/Projects/Server/Main.cs @@ -116,8 +116,6 @@ namespace Server internal static bool HaltOnWarning{ get; private set; } - public static List DataDirectories{ get; } = new List(); - public static Assembly Assembly{ get; set; } public static Version Version => Assembly.GetName().Version; @@ -213,13 +211,14 @@ namespace Server public static string FindDataFile(string path) { - if (DataDirectories.Count == 0) + Configuration config = Configuration.Instance; + if (config.DataDirectories.Count == 0) throw new InvalidOperationException( "Attempted to FindDataFile before DataDirectories list has been filled."); string fullPath = null; - foreach (string p in DataDirectories) + foreach (string p in config.DataDirectories) { fullPath = Path.Combine(p, path); @@ -383,14 +382,10 @@ namespace Server if (BaseDirectory.Length > 0) Directory.SetCurrentDirectory(BaseDirectory); - Timer.TimerThread ttObj = new Timer.TimerThread(); - timerThread = new Thread(ttObj.TimerMain) - { - Name = "Timer Thread" - }; Version ver = Assembly.GetName().Version; + Console.ForegroundColor = ConsoleColor.Green; // Added to help future code support on forums, as a 'check' people can ask for to it see if they recompiled core or not Console.WriteLine("ModernUO - [https://github.com/kamronbatman/ModernUO] Version {0}.{1}.{2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision); @@ -400,6 +395,14 @@ namespace Server Console.WriteLine("Core: Running on .NET Framework Version {0}.{1}.{2}", Environment.Version.Major, Environment.Version.Minor, Environment.Version.Build); #endif + Console.ResetColor(); + Console.WriteLine(); + + Timer.TimerThread ttObj = new Timer.TimerThread(); + timerThread = new Thread(ttObj.TimerMain) + { + Name = "Timer Thread" + }; string s = Arguments; diff --git a/Projects/Server/TileData.cs b/Projects/Server/TileData.cs index ce23abc0c..ff97764af 100644 --- a/Projects/Server/TileData.cs +++ b/Projects/Server/TileData.cs @@ -294,9 +294,11 @@ namespace Server } else { + Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("tiledata.mul was not found"); - Console.WriteLine("Make sure your Scripts/Misc/DataPath.cs is properly configured"); + Console.WriteLine("Make sure your modernuo.json is properly configured"); Console.WriteLine("After pressing return an exception will be thrown and the server will terminate"); + Console.ResetColor(); throw new Exception($"TileData: {filePath} not found"); } @@ -321,4 +323,4 @@ namespace Server return Encoding.ASCII.GetString(m_StringBuffer, 0, count); } } -} \ No newline at end of file +}