Skip to content

Commit

Permalink
Remove path argument from Load/Save of ServerList to prevent unsynchr…
Browse files Browse the repository at this point in the history
…onised usage

Also remove lines which should have been removed after V1.5 release
  • Loading branch information
Jannify committed Dec 15, 2024
1 parent 8b2f1dc commit e134821
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ void LateAddButton(IPEndPoint serverEndPoint)
{
Log.Info($"Adding LAN server: {serverEndPoint}");
// Add ServerList entry to keep indices in sync with servers UI, to enable removal by index
ServerList.Instance.Add(new ServerList.Entry("LAN Server", serverEndPoint.Address.ToString(), serverEndPoint.Port.ToString(), false));
ServerList.Instance.Add(new ServerList.Entry("LAN Server", serverEndPoint.Address, serverEndPoint.Port, false));
CreateServerButton("LAN Server", serverEndPoint.Address.ToString(), serverEndPoint.Port, true);
}
}
Expand Down
235 changes: 113 additions & 122 deletions NitroxModel/Serialization/ServerList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,166 +4,157 @@
using System.Linq;
using System.Net;
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<Entry> 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<Entry> 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 static string DefaultFile => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Nitrox", SERVERS_FILE_NAME);
public IEnumerable<Entry> Entries => entries;

public IEnumerable<Entry> Entries => entries;
public static ServerList Refresh()
{
return instance = From();
}

public static ServerList Refresh()
public static ServerList From()
{
// 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)
/// <summary>
/// If true, entry will be saved to storage.
/// </summary>
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; }

/// <summary>
/// If true, entry will be saved to storage.
/// </summary>
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, 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}";
}
}
}

0 comments on commit e134821

Please sign in to comment.