2024-12-22 16:38:47 +03:00
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2024-12-27 08:22:17 +03:00
|
|
|
using System.Text.Json;
|
2024-12-22 16:38:47 +03:00
|
|
|
|
2025-01-05 17:05:23 +03:00
|
|
|
namespace Nebula.Shared.Services;
|
2024-12-22 16:38:47 +03:00
|
|
|
|
2024-12-27 19:15:33 +03:00
|
|
|
public class ConVar<T>
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
|
|
|
|
public string Name { get; }
|
2024-12-27 19:15:33 +03:00
|
|
|
public Type Type => typeof(T);
|
|
|
|
|
public T? DefaultValue { get; }
|
2024-12-28 08:29:01 +03:00
|
|
|
|
|
|
|
|
public ConVar(string name, T? defaultValue = default)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
2024-12-22 16:38:47 +03:00
|
|
|
DefaultValue = defaultValue;
|
|
|
|
|
}
|
2024-12-27 19:15:33 +03:00
|
|
|
}
|
2024-12-22 16:38:47 +03:00
|
|
|
|
2024-12-27 19:15:33 +03:00
|
|
|
public static class ConVarBuilder
|
|
|
|
|
{
|
|
|
|
|
public static ConVar<T> Build<T>(string name, T? defaultValue = default)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
|
|
|
throw new ArgumentException("ConVar name cannot be null or whitespace.", nameof(name));
|
|
|
|
|
|
2024-12-27 19:15:33 +03:00
|
|
|
return new ConVar<T>(name, defaultValue);
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ServiceRegister]
|
|
|
|
|
public class ConfigurationService
|
|
|
|
|
{
|
2024-12-27 08:22:17 +03:00
|
|
|
private readonly FileService _fileService;
|
|
|
|
|
private readonly DebugService _debugService;
|
|
|
|
|
|
|
|
|
|
public ConfigurationService(FileService fileService, DebugService debugService)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
_fileService = fileService ?? throw new ArgumentNullException(nameof(fileService));
|
|
|
|
|
_debugService = debugService ?? throw new ArgumentNullException(nameof(debugService));
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2024-12-27 19:15:33 +03:00
|
|
|
public T? GetConfigValue<T>(ConVar<T> conVar)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
ArgumentNullException.ThrowIfNull(conVar);
|
2024-12-22 16:38:47 +03:00
|
|
|
|
2024-12-27 08:22:17 +03:00
|
|
|
try
|
|
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
if (_fileService.ConfigurationApi.TryOpen(GetFileName(conVar), out var stream))
|
|
|
|
|
{
|
|
|
|
|
using (stream)
|
|
|
|
|
{
|
|
|
|
|
var obj = JsonSerializer.Deserialize<T>(stream);
|
|
|
|
|
if (obj != null)
|
|
|
|
|
{
|
|
|
|
|
_debugService.Log($"Successfully loaded config: {conVar.Name}");
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-12-27 08:22:17 +03:00
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
_debugService.Error($"Error loading config for {conVar.Name}: {e.Message}");
|
2024-12-27 08:22:17 +03:00
|
|
|
}
|
2024-12-28 08:29:01 +03:00
|
|
|
|
|
|
|
|
_debugService.Log($"Using default value for config: {conVar.Name}");
|
|
|
|
|
return conVar.DefaultValue;
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2024-12-28 08:29:01 +03:00
|
|
|
public void SetConfigValue<T>(ConVar<T> conVar, T value)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
ArgumentNullException.ThrowIfNull(conVar);
|
|
|
|
|
if (value == null) throw new ArgumentNullException(nameof(value));
|
2024-12-27 19:15:33 +03:00
|
|
|
|
2024-12-28 08:29:01 +03:00
|
|
|
if (!conVar.Type.IsInstanceOfType(value))
|
|
|
|
|
{
|
|
|
|
|
_debugService.Error($"Type mismatch for config {conVar.Name}. Expected {conVar.Type}, got {value.GetType()}.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-27 08:22:17 +03:00
|
|
|
try
|
|
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
_debugService.Log($"Saving config: {conVar.Name}");
|
|
|
|
|
var serializedData = JsonSerializer.Serialize(value);
|
|
|
|
|
|
|
|
|
|
using var stream = new MemoryStream();
|
2024-12-30 22:23:55 +03:00
|
|
|
using var writer = new StreamWriter(stream);
|
|
|
|
|
writer.Write(serializedData);
|
|
|
|
|
writer.Flush();
|
|
|
|
|
stream.Seek(0, SeekOrigin.Begin);
|
2024-12-28 08:29:01 +03:00
|
|
|
|
2024-12-27 19:15:33 +03:00
|
|
|
_fileService.ConfigurationApi.Save(GetFileName(conVar), stream);
|
2024-12-27 08:22:17 +03:00
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
_debugService.Error($"Error saving config for {conVar.Name}: {e.Message}");
|
2024-12-27 08:22:17 +03:00
|
|
|
}
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2024-12-28 08:29:01 +03:00
|
|
|
private static string GetFileName<T>(ConVar<T> conVar)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
return $"{conVar.Name}.json";
|
2024-12-27 08:22:17 +03:00
|
|
|
}
|
2024-12-27 19:15:33 +03:00
|
|
|
}
|
2024-12-27 08:22:17 +03:00
|
|
|
|
2024-12-28 08:29:01 +03:00
|
|
|
public static class ConfigExtensions
|
2024-12-27 19:15:33 +03:00
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
public static bool TryGetConfigValue<T>(this ConfigurationService configurationService, ConVar<T> conVar, [NotNullWhen(true)] out T? value)
|
2024-12-27 08:22:17 +03:00
|
|
|
{
|
2024-12-28 08:29:01 +03:00
|
|
|
ArgumentNullException.ThrowIfNull(configurationService);
|
|
|
|
|
ArgumentNullException.ThrowIfNull(conVar);
|
|
|
|
|
|
2024-12-27 08:22:17 +03:00
|
|
|
value = configurationService.GetConfigValue(conVar);
|
2024-12-22 16:38:47 +03:00
|
|
|
return value != null;
|
|
|
|
|
}
|
|
|
|
|
}
|