From a985cc049be989834e5f21805185cd6738abe42c Mon Sep 17 00:00:00 2001 From: Jannify <23176718+Jannify@users.noreply.github.com> Date: Sun, 15 Dec 2024 21:50:23 +0100 Subject: [PATCH] Remove path argument from Load/Save of ServerList to prevent unsynchronised usage --- NitroxModel/Serialization/ServerList.cs | 239 ++++++++++++------------ 1 file changed, 119 insertions(+), 120 deletions(-) diff --git a/NitroxModel/Serialization/ServerList.cs b/NitroxModel/Serialization/ServerList.cs index 7192f5c069..11d5a7d061 100644 --- a/NitroxModel/Serialization/ServerList.cs +++ b/NitroxModel/Serialization/ServerList.cs @@ -6,164 +6,163 @@ using NitroxModel.Helper; using NitroxModel.Platforms.OS.Shared; -namespace NitroxModel.Serialization +namespace NitroxModel.Serialization; + +public class ServerList { - public class ServerList - { - private const string SERVERS_FILE_NAME = "servers"; - public const int DEFAULT_PORT = 11000; - private static ServerList instance; - private readonly List entries = new(); - public static ServerList Instance => instance ??= Refresh(); + private const string SERVERS_FILE_NAME = "servers"; + public const int DEFAULT_PORT = 11000; + private static ServerList instance; + private readonly List entries = new(); + public static ServerList Instance => instance ??= Refresh(); - private static ServerList Default + private static ServerList Default + { + get { - get - { - ServerList list = new(); - list.Add(new Entry("Your server", "127.0.0.1", DEFAULT_PORT)); - return list; - } + ServerList list = new(); + list.Add(new Entry("Your server", "127.0.0.1", DEFAULT_PORT)); + return list; } + } + + public static string DefaultFile => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Nitrox", SERVERS_FILE_NAME); + + public IEnumerable Entries => entries; - public static string DefaultFile => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Nitrox", SERVERS_FILE_NAME); + public static ServerList Refresh() + { + return instance = From(); + } - public IEnumerable Entries => entries; + public static ServerList From() + { + // TODO: Remove backward compatibility after 1.5.0.0 release (no need to move old server file). + FileSystem.Instance.ReplaceFile(SERVERS_FILE_NAME, DefaultFile); - public static ServerList Refresh() + // Create file if it doesn't exist yet. + string file = DefaultFile; + if (!File.Exists(file)) { - return instance = From(DefaultFile); + instance = Default; + instance.Save(); + return instance; } - public static ServerList From(string file = null) + ServerList list = new(); + foreach (string line in File.ReadAllLines(file)) { - // TODO: Remove backward compatibility after 1.5.0.0 release (no need to move old server file). - FileSystem.Instance.ReplaceFile(SERVERS_FILE_NAME, DefaultFile); - - // Create file if it doesn't exist yet. - file ??= DefaultFile; - if (!File.Exists(file)) + Entry entry = Entry.FromLine(line); + if (entry == null) { - instance = Default; - instance.Save(file); - return instance; + continue; } - ServerList list = new(); - foreach (string line in File.ReadAllLines(file)) - { - Entry entry = Entry.FromLine(line); - if (entry == null) - { - continue; - } + list.entries.Add(entry); + } + return list; + } + + public void Add(Entry entry) + { + entries.Add(entry); + } + + public void Save() + { + string file = DefaultFile; - list.entries.Add(entry); + using StreamWriter writer = new(new FileStream(file, FileMode.Create, FileAccess.Write)); + foreach (Entry entry in entries) + { + if (entry.Persist) + { + writer.WriteLine(entry.ToString()); } - return list; } + } - public void Add(Entry entry) + public void RemoveAt(int index) + { + if (index < 0 || index >= entries.Count) { - entries.Add(entry); + throw new ArgumentOutOfRangeException(nameof(index)); } - public void Save(string file = null) - { - file ??= DefaultFile; + entries.RemoveAt(index); + } - using StreamWriter writer = new(new FileStream(file, FileMode.Create, FileAccess.Write)); - foreach (Entry entry in entries) - { - if (entry.Persist) - { - writer.WriteLine(entry.ToString()); - } - } - } + public class Entry + { + public string Name { get; } + public string Address { get; } + public int Port { get; } - public void RemoveAt(int index) + /// + /// If true, entry will be saved to storage. + /// + public bool Persist { get; } + + public Entry(string name, string address, int port, bool persist = true) { - if (index < 0 || index >= entries.Count) + if (string.IsNullOrWhiteSpace(name)) { - throw new ArgumentOutOfRangeException(nameof(index)); + throw new ArgumentException("name in ServerList.Entry constructor can't be null or whitespace"); } + Validate.NotNull(address); - entries.RemoveAt(index); + Name = name.Trim(); + Address = address.Trim(); + Port = port; + Persist = persist; } - public class Entry + public Entry(string name, IPAddress address, int port, bool persist = true) : this(name, address.ToString(), port, persist) { - public string Name { get; } - public string Address { get; } - public int Port { get; } - - /// - /// If true, entry will be saved to storage. - /// - public bool Persist { get; } + } - public Entry(string name, string address, int port, bool persist = true) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException("name in ServerList.Entry constructor can't be null or whitespace"); - } - Validate.NotNull(address); - - Name = name.Trim(); - Address = address.Trim(); - Port = port; - Persist = persist; - } + public Entry(string name, string address, string port, bool persist = true) : this(name, address, int.Parse(port), persist) + { + } - public Entry(string name, IPAddress address, int port, bool persist = true) : this(name, address.ToString(), port, persist) + public static Entry FromLine(string line) + { + if (string.IsNullOrWhiteSpace(line)) { + return null; } - - public Entry(string name, string address, string port, bool persist = true) : this(name, address, int.Parse(port), persist) + string[] parts = line.Split('|'); + int port; + string address; + switch (parts.Length) { + case 2: + // Split from address as format "hostname:port". + string[] addressSplit = parts[1].Split(':'); + address = addressSplit[0]; + if (!int.TryParse(addressSplit.ElementAtOrDefault(1), out port)) + { + port = DEFAULT_PORT; + } + break; + case 3: + address = parts[1].Trim(); + if (!int.TryParse(parts[2], out port)) + { + port = DEFAULT_PORT; + } + break; + default: + throw new Exception($"Expected server entry to have 2 or 3 parts: {line}"); } - public static Entry FromLine(string line) - { - if (string.IsNullOrWhiteSpace(line)) - { - return null; - } - string[] parts = line.Split('|'); - int port; - string address; - switch (parts.Length) - { - case 2: - // Split from address as format "hostname:port". - string[] addressSplit = parts[1].Split(':'); - address = addressSplit[0]; - if (!int.TryParse(addressSplit.ElementAtOrDefault(1), out port)) - { - port = DEFAULT_PORT; - } - break; - case 3: - address = parts[1].Trim(); - if (!int.TryParse(parts[2], out port)) - { - port = DEFAULT_PORT; - } - break; - default: - throw new Exception($"Expected server entry to have 2 or 3 parts: {line}"); - } - - string name = parts[0].Trim(); - return new Entry(name, address, port); - } + string name = parts[0].Trim(); + return new Entry(name, address, port); + } - public override string ToString() - { - return $"{Name}|{Address}|{Port}"; - } + public override string ToString() + { + return $"{Name}|{Address}|{Port}"; } } }