using System.Collections.Generic; using System.IO; using System.Security.Cryptography; using System.Text; using UnityEngine; using UnityEngine.Events; public class SettingsManager : MonoBehaviour { public static SettingsManager instance; private static string SETTINGS_FILE_PATH => Path.Combine(Application.persistentDataPath, "GameSettings.json"); public static SettingsContainer Container; public static UnityEvent OnSettingsChanged; public static void Initialize() //добавить инициализацию в менеджера в парвильное место в порядке { OnSettingsChanged = new UnityEvent(); Container = LoadContainerAuto(); OnSettingsChanged?.Invoke(); } public static void ChangeSetting(Setting setting, int direction) { bool changed = setting.ChangeValue(direction); if (changed) { SaveContainerToFile(); OnSettingsChanged?.Invoke(); } } //Геттеры возможно будут статикой public static bool GetBool(string id, bool _default) { var setting = Container.TryGetSetting(id); if (setting != null) { if (setting.Type != SettingType.Bool) Debug.LogWarning($"Тип настройки {id} не соответсвует bool"); return setting.BoolValue; } else { return _default; } } public static int GetInt(string id, int _default) { var setting = Container.TryGetSetting(id); if (setting != null) { if (setting.Type != SettingType.Int) Debug.LogWarning($"Тип настройки {id} не соответсвует int"); return setting.IntValue; } else { return _default; } } public static float GetFloat(string id, float _default) { var setting = Container.TryGetSetting(id); if (setting != null) { if (setting.Type != SettingType.Float) Debug.LogWarning($"Тип настройки {id} не соответсвует float"); return setting.FloatValue; } else { return _default; } } public static string GetString(string id, string _default) { var setting = Container.TryGetSetting(id); if (setting != null) { if (setting.Type != SettingType.String) Debug.LogWarning($"Тип настройки {id} не соответсвует string"); return setting.StringValue; } else { return _default; } } private static string GetSettingsHash(List settings) { StringBuilder sb = new(); foreach (Setting setting in settings) { sb.Append(setting.Id); sb.Append(setting.Alias); sb.Append(setting.Group); sb.Append(setting.Type); } byte[] inputBytes = Encoding.UTF8.GetBytes(sb.ToString()); using MD5 md5 = MD5.Create(); byte[] hashBytes = md5.ComputeHash(inputBytes); return Encoding.UTF8.GetString(hashBytes); } public static void SaveContainerToFile() { SettingDataWrapper dataWrapper = new SettingDataWrapper(Container.Settings); string json = JsonUtility.ToJson(dataWrapper); string jsonEnc = CryptoUtil.EncryptJson(json, "RR_SeTtInGs"); File.WriteAllText(SETTINGS_FILE_PATH, jsonEnc); } private static void SaveContainerToFile(SettingsContainer container) { SettingDataWrapper dataWrapper = new SettingDataWrapper(container.Settings); string json = JsonUtility.ToJson(dataWrapper, true); string jsonEnc = CryptoUtil.EncryptJson(json, "RR_SeTtInGs"); File.WriteAllText(SETTINGS_FILE_PATH, jsonEnc); } private static SettingsContainer GetContainerFromDefault() { SettingsContainer container = new SettingsContainer(GetDefaultSettings()); SaveContainerToFile(container); return container; } private static SettingsContainer GetContainerFromFile() { string jsonEnc = File.ReadAllText(SETTINGS_FILE_PATH); string json = CryptoUtil.DecryptJson(jsonEnc, "RR_SeTtInGs"); SettingDataWrapper dataWrapper = JsonUtility.FromJson(json); SettingsContainer container = new SettingsContainer(dataWrapper); return container; } private static SettingsContainer LoadContainerAuto() { bool shouldLoadDefault = !SettingsFileExists() || !IsSavedSettingsValid(); return shouldLoadDefault ? GetContainerFromDefault() : GetContainerFromFile(); } private static bool SettingsFileExists() { if (!File.Exists(SETTINGS_FILE_PATH)) { Debug.LogWarning($"Файл не найден по пути: {SETTINGS_FILE_PATH}"); return false; } return true; } private static bool IsSavedSettingsValid() { string savedHash = GetSettingsHash(GetContainerFromFile().Settings); string defaultHash = GetSettingsHash(GetDefaultSettings()); bool valid = string.Equals(savedHash, defaultHash); return valid; } private static List GetDefaultSettings() { var settings = new List(); settings.Add(new Setting(id: "MusicVolume", alias: "Громкость музыки", group: "Звук и озвучка", type: SettingType.Float, cycling: false, value: 0.5f, min: 0f, max: 1f, step: 0.01f)); settings.Add(new Setting(id: "SoundsVolume", alias: "Громкость эффектов и голоса", group: "Звук и озвучка", type: SettingType.Float, cycling: false, value: 0.5f, min: 0f, max: 1f, step: 0.01f)); settings.Add(new Setting(id: "PromoVolume", alias: "Громкость промо ролика", group: "Звук и озвучка", type: SettingType.Float, cycling: false, value: 0.5f, min: 0f, max: 1f, step: 0.01f)); settings.Add(new Setting(id: "Prizing", alias: "Выдача призов при игре с ботом", group: "Игровой процесс", type: SettingType.Bool, cycling: false, value: true)); settings.Add(new Setting(id: "EnableVoices", alias: "Голосовые реплики", group: "Звук и озвучка", type: SettingType.Bool, cycling: false, value: true)); settings.Add(new Setting(id: "Difficulty", alias: "Сложность ботов", group: "Игровой процесс", type: SettingType.String, cycling: false, value: "Средняя", allowedValues: new() { "Легкая", "Средняя", "Сложная" })); settings.Add(new Setting(id: "Freeplay", alias: "Бесплатная игра", group: "Оплата и цены", type: SettingType.Bool, cycling: false, value: false)); settings.Add(new Setting(id: "ShowNumber", alias: "Показывать контакты администрации", group: "Контакты и поддержка", type: SettingType.Bool, cycling: false, value: true)); settings.Add(new Setting(id: "FastCheck", alias: "Быстрая проверка счетчиков", group: "Быстрые проверки", type: SettingType.Bool, cycling: false, value: true)); settings.Add(new Setting(id: "FastCheckPrizes", alias: "Быстрая проверка призов", group: "Быстрые проверки", type: SettingType.Bool, cycling: false, value: true)); settings.Add(new Setting(id: "PrizingWhenError", alias: "Выдавать приз при ошибке", group: "Призы и выдача", type: SettingType.Bool, cycling: false, value: true)); settings.Add(new Setting(id: "DisplayPrizingError", alias: "Вывод ошибки выдачи в меню", group: "Призы и выдача", type: SettingType.Bool, cycling: false, value: true)); //от 25.12.2025 settings.Add(new Setting(id: "BaseBotDifficulty", alias: "Текущая сложность аппарата", group: "Игровой процесс", type: SettingType.String, cycling: false, value: "Повышенная", allowedValues: new() { "Обычная", "Повышенная", "Фиксированная"})); //от 26.12.2025 settings.Add(new Setting(id: "DisplayNoPrizes", alias: "Выводить призы закончились", group: "Призы и выдача", type: SettingType.Bool, cycling: false, value: false)); //от 16.01.2026 settings.Add(new Setting(id: "PasswordOnSettings", alias: "Вход в настройки по паролю", group: "Сервис", type: SettingType.Bool, cycling: false, value: false)); settings.Add(new Setting(id: "TakeOrRisk", alias: "Забрать или рискнуть", group: "Призы и выдача", type: SettingType.Bool, cycling: false, value: true)); return settings; } }