Skip to content

Commit

Permalink
auto reload config
Browse files Browse the repository at this point in the history
  • Loading branch information
BillyGalbreath committed Apr 2, 2024
1 parent f4b59c8 commit b2dd1d1
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 15 deletions.
1 change: 0 additions & 1 deletion src/Common/Util/FileUtil.cs
Expand Up @@ -6,7 +6,6 @@
namespace LiveMap.Common.Util;

public static class FileUtil {
public static readonly string ConfigFile = Path.Combine(GamePaths.ModConfig, $"{LiveMapMod.Id}.yml");
public static readonly string DataDir = Path.Combine(GamePaths.DataPath, "ModData", LiveMapMod.Api.World.SavegameIdentifier, "LiveMap");
public static readonly string ColormapFile = Path.Combine(DataDir, "colormap.yaml");
public static readonly string WebDir = Path.Combine(DataDir, "web");
Expand Down
43 changes: 29 additions & 14 deletions src/Server/Configuration/Config.cs
Expand Up @@ -2,7 +2,6 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using LiveMap.Common.Util;
using Vintagestory.API.Config;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
Expand Down Expand Up @@ -31,21 +30,32 @@ public sealed class Config {
""")]
public LoggerConfig Logger = new();

private static string ConfigFile => Path.Combine(GamePaths.ModConfig, $"{LiveMapMod.Id}.yml");

public static Config Instance { get; private set; } = null!;

private static FileWatcher? _watcher;

public static void Reload() {
Instance = Write(Read<Config>());
Instance = Write(Read());

_watcher ??= new FileWatcher();

// todo - reset whatever needs to be reset
// write new settings.json file in tiles dir

Common.Util.Logger.Info($"Loaded config from {ConfigFile}");
}

private static T Read<T>() where T : new() {
private static Config Read() {
try {
string yaml = File.ReadAllText(FileUtil.ConfigFile, Encoding.UTF8);
string yaml = File.ReadAllText(ConfigFile, Encoding.UTF8);
return new DeserializerBuilder()
.IgnoreUnmatchedProperties()
.WithNamingConvention(NullNamingConvention.Instance)
.Build().Deserialize<T>(yaml);
.Build().Deserialize<Config>(yaml);
} catch (Exception) {
return new T();
return new Config();
}
}

Expand All @@ -56,9 +66,14 @@ public sealed class Config {
.WithNamingConvention(NullNamingConvention.Instance)
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull)
.Build().Serialize(config);
File.WriteAllText(FileUtil.ConfigFile, yaml, Encoding.UTF8);
File.WriteAllText(ConfigFile, yaml, Encoding.UTF8);
return config;
}

public static void Dispose() {
_watcher?.Dispose();
_watcher = null;
}
}

[SuppressMessage("ReSharper", "ConvertToConstant.Global")]
Expand Down Expand Up @@ -89,18 +104,18 @@ public class ZoomConfig {
public int Default = 0;

[YamlMember(Order = 1, Description = """
The maximum zoom out you can do on the map.
Each additional level requires a new set of tiles
to be rendered, so don't go too wild here.
""")]
public int MaxOut = 8;

[YamlMember(Order = 2, Description = """
Extra zoom in layers will stretch the original
tile images so you can zoom in further without
the extra cost of rendering more tiles.
""")]
public int MaxIn = 3;

[YamlMember(Order = 2, Description = """
The maximum zoom out you can do on the map.
Each additional level requires a new set of tiles
to be rendered, so don't go too wild here.
""")]
public int MaxOut = 8;
}

[SuppressMessage("ReSharper", "ConvertToConstant.Global")]
Expand Down
73 changes: 73 additions & 0 deletions src/Server/Configuration/FileWatcher.cs
@@ -0,0 +1,73 @@
using System.IO;
using LiveMap.Common.Util;
using Vintagestory.API.Config;

namespace LiveMap.Server.Configuration;

public class FileWatcher {
private readonly FileSystemWatcher _watcher;
private bool _queued;

public FileWatcher() {
_watcher = new FileSystemWatcher(GamePaths.ModConfig);

_watcher.Filter = $"{LiveMapMod.Id}.yml";
_watcher.IncludeSubdirectories = false;
_watcher.EnableRaisingEvents = true;

_watcher.Changed += Changed;
_watcher.Created += Changed;
_watcher.Deleted += Changed;
_watcher.Renamed += Changed;
_watcher.Error += Error;
}

private void Changed(object sender, FileSystemEventArgs e) {
QueueReload(e.ChangeType.ToString().ToLowerInvariant());
}

private void Error(object sender, ErrorEventArgs e) {
Logger.Error(e.GetException().ToString());
QueueReload();
}

/// <summary>
/// My workaround for <a href='https://github.com/dotnet/runtime/issues/24079'>dotnet#24079</a>.
/// </summary>
private void QueueReload(string? changeType = null) {
// check if already queued for reload
if (_queued) {
return;
}

// mark as queued
_queued = true;

// inform console/log
if (changeType != null) {
Logger.Info($"Detected the config was {changeType}");
}

// wait for other changes to process
LiveMapMod.Api.Event.RegisterCallback(_ => {
// reload the config
Config.Reload();
// wait some more to remove this change from the queue since the reload triggers another write
LiveMapMod.Api.Event.RegisterCallback(_ => {
// unmark as queued
_queued = false;
}, 100);
}, 100);
}

public void Dispose() {
_watcher.Changed -= Changed;
_watcher.Created -= Changed;
_watcher.Deleted -= Changed;
_watcher.Renamed -= Changed;
_watcher.Error -= Error;

_watcher.Dispose();
}
}
2 changes: 2 additions & 0 deletions src/Server/LiveMapServer.cs
Expand Up @@ -94,6 +94,8 @@ public sealed class LiveMapServer : Common.LiveMap {

Colormap.Dispose();

Config.Dispose();

_patches.Dispose();
}
}

0 comments on commit b2dd1d1

Please sign in to comment.