using System.Text.Json; using System.Text.Json.Serialization; namespace XafPet.Desktop.PetEngine; [JsonConverter(typeof(JsonStringEnumConverter))] public enum PetType { Animal, Human, Custom } /// 宠物形象配置(pet-config.json) public sealed class PetConfig { [JsonPropertyName("version")] public string Version { get; set; } = "1.0"; [JsonPropertyName("type")] public PetType Type { get; set; } = PetType.Custom; [JsonPropertyName("species")] public string Species { get; set; } = "other"; [JsonPropertyName("gender")] public string Gender { get; set; } = "neutral"; [JsonPropertyName("image_base_url")] public string ImageBaseUrl { get; set; } = ""; [JsonPropertyName("default_image")] public string DefaultImage { get; set; } = "standing.png"; [JsonPropertyName("actions")] public Dictionary Actions { get; set; } = new(); [JsonPropertyName("sounds")] public Dictionary Sounds { get; set; } = new(); [JsonPropertyName("parameters")] public PetParameters Parameters { get; set; } = new(); [JsonIgnore] public int CustomStateCount => Actions.Keys.Count(k => k.StartsWith("custom_state_")); /// 解析 JSON 字符串;缺省 actions 时补默认映射(key=value) public static PetConfig Parse(string json) { var config = JsonSerializer.Deserialize(json) ?? throw new JsonException("pet-config.json 反序列化结果为 null"); if (config.Actions.Count == 0) { config.Actions = new Dictionary { ["idle"] = "idle", ["happy"] = "happy", ["busy"] = "busy", ["sleeping"] = "sleeping" }; } return config; } public string GetActionForState(string stateName) => Actions.TryGetValue(stateName, out var v) ? v : stateName; } public sealed class PetParameters { [JsonPropertyName("move_distance")] public int MoveDistance { get; set; } = 15; [JsonPropertyName("animation_speed")] public double AnimationSpeed { get; set; } = 1.0; [JsonPropertyName("interaction_timeout")] public int InteractionTimeout { get; set; } = 300; // 秒 }