using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using UnityEngine; namespace RebootKit.Engine.Foundation { [AttributeUsage(AttributeTargets.Field)] public class ConfigVarAttribute : Attribute { public ConfigVarAttribute(string name, float defaultValue, string description = "", CVarFlags flags = CVarFlags.Client) { Name = name; Description = description; Value = new CVarValue(defaultValue); Flags = flags; } public ConfigVarAttribute(string name, double defaultValue, string description = "", CVarFlags flags = CVarFlags.Client) { Name = name; Description = description; Value = new CVarValue(defaultValue); Flags = flags; } public ConfigVarAttribute(string name, string defaultValue, string description = "", CVarFlags flags = CVarFlags.Client) { Name = name; Description = description; Value = new CVarValue(defaultValue); Flags = flags; } public ConfigVarAttribute(string name, int defaultValue, string description = "", CVarFlags flags = CVarFlags.Client) { Name = name; Description = description; Value = new CVarValue(defaultValue); Flags = flags; } internal string Name { get; } internal string Description { get; } internal CVarValue Value { get; } internal CVarFlags Flags { get; } } public static class ConfigVarsContainer { static readonly Logger s_logger = new Logger(nameof(ConfigVarsContainer)); static readonly List s_configVars = new List(); public static void Register(ConfigVar cvar) { if (Get(cvar.name) != null) { throw new Exception($"CVar with name '{cvar.name}' already exists"); } s_configVars.Add(cvar); s_logger.Info($"Registered CVar: {cvar.name}"); } public static void Clear() { s_configVars.Clear(); s_logger.Info("Cleared all CVars"); } public static ConfigVar Get(string name) { foreach (ConfigVar configVar in s_configVars) { if (configVar.name.Equals(name, StringComparison.Ordinal)) { return configVar; } } return null; } public static IEnumerable All() => s_configVars; public static void Init() { Clear(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type[] types = assembly.GetTypes(); foreach (Type type in types) { FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); foreach (FieldInfo field in fields) { if (Attribute.IsDefined(field, typeof(ConfigVarAttribute))) { ConfigVarAttribute cvarAttribute = field.GetCustomAttribute(); ConfigVar cvar = Get(cvarAttribute.Name); if (cvar == null) { cvar = new ConfigVar(cvarAttribute.Name, cvarAttribute.Value, cvarAttribute.Description) { flags = cvarAttribute.Flags }; Register(cvar); } field.SetValue(null, cvar); } } } } Load(); } public static void Save() { string path = Application.persistentDataPath + "/" + RConsts.k_CVarsFilename; s_logger.Info("Saving cvars to file: " + path); StringBuilder sb = new StringBuilder(); foreach (ConfigVar cvar in All()) { if ((cvar.flags & CVarFlags.ReadOnly) == 0) { sb.AppendFormat("{0} {1}\n", cvar.name, cvar); } } File.WriteAllText(path, sb.ToString()); } public static void Load() { string path = Application.persistentDataPath + "/" + RConsts.k_CVarsFilename; if (!File.Exists(path)) { s_logger.Info("CVar file not found, skipping load"); return; } s_logger.Info("Loading cvars from file: " + path); string[] lines = File.ReadAllLines(path); foreach (string line in lines) { string[] parts = line.Split(' '); if (parts.Length < 2) { continue; } string name = parts[0]; string value = parts[1]; ConfigVar cvar = Get(name); if (cvar != null) { cvar.Value.CopyFrom(new CVarValue(value)); s_logger.Info($"Loaded CVar: {name} = {value}"); } else { cvar = new ConfigVar(name, value) { flags = CVarFlags.User }; cvar.ParseFromString(value); Register(cvar); } } } } }