Add EventDef notices, morning and lesson bells, and info toasts.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -318,6 +318,7 @@ public sealed class CatalogLoader
|
||||
var topics = new Dictionary<string, TopicDef>(StringComparer.Ordinal);
|
||||
var orientations = new Dictionary<string, OrientationDef>(StringComparer.Ordinal);
|
||||
var affinity = new Dictionary<string, AffinityRulesDef>(StringComparer.Ordinal);
|
||||
var events = new Dictionary<string, EventDef>(StringComparer.Ordinal);
|
||||
|
||||
foreach (var (key, json) in resolved)
|
||||
{
|
||||
@@ -392,6 +393,9 @@ public sealed class CatalogLoader
|
||||
case DefKind.AffinityRules:
|
||||
affinity[key.Name] = Jsonc.Deserialize<AffinityRulesDef>(json);
|
||||
break;
|
||||
case DefKind.Event:
|
||||
events[key.Name] = Jsonc.Deserialize<EventDef>(json);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,6 +424,7 @@ public sealed class CatalogLoader
|
||||
topics,
|
||||
orientations,
|
||||
affinity,
|
||||
events,
|
||||
ru,
|
||||
en);
|
||||
}
|
||||
@@ -534,6 +539,7 @@ public sealed class CatalogLoader
|
||||
}
|
||||
|
||||
PeopleDefValidator.Validate(catalog, log);
|
||||
EventDefValidator.Validate(catalog);
|
||||
}
|
||||
|
||||
private static void WarnMissingLabels(DefCatalog catalog, IContentLog log)
|
||||
@@ -571,7 +577,8 @@ public sealed class CatalogLoader
|
||||
.Concat(Enumerate(catalog.Colors.Values))
|
||||
.Concat(Enumerate(catalog.Topics.Values))
|
||||
.Concat(Enumerate(catalog.Orientations.Values))
|
||||
.Concat(Enumerate(catalog.Affinity.Values));
|
||||
.Concat(Enumerate(catalog.Affinity.Values))
|
||||
.Concat(Enumerate(catalog.Events.Values));
|
||||
|
||||
static IEnumerable<Def> Enumerate(IEnumerable<Def> defs) => defs.Where(def => !def.Abstract);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ public sealed class DefCatalog
|
||||
IReadOnlyDictionary<string, TopicDef> topics,
|
||||
IReadOnlyDictionary<string, OrientationDef> orientations,
|
||||
IReadOnlyDictionary<string, AffinityRulesDef> affinity,
|
||||
IReadOnlyDictionary<string, EventDef> events,
|
||||
IReadOnlyDictionary<string, string> ru,
|
||||
IReadOnlyDictionary<string, string> en)
|
||||
{
|
||||
@@ -58,6 +59,7 @@ public sealed class DefCatalog
|
||||
Topics = topics;
|
||||
Orientations = orientations;
|
||||
Affinity = affinity;
|
||||
Events = events;
|
||||
_ru = ru;
|
||||
_en = en;
|
||||
AnyNeedDecays = needs.Values.Any(need => !need.Abstract && need.DecayPerHour > 0f);
|
||||
@@ -121,6 +123,8 @@ public sealed class DefCatalog
|
||||
|
||||
public IReadOnlyDictionary<string, AffinityRulesDef> Affinity { get; }
|
||||
|
||||
public IReadOnlyDictionary<string, EventDef> Events { get; }
|
||||
|
||||
/// <summary>The one concrete staffing ruleset, or null when a pack has not defined it.</summary>
|
||||
public StaffingDef? StaffingRules => Staffing.Values.FirstOrDefault(def => !def.Abstract);
|
||||
|
||||
@@ -163,6 +167,7 @@ public sealed class DefCatalog
|
||||
DefKind.Topic => Topics.GetValueOrDefault(defName),
|
||||
DefKind.Orientation => Orientations.GetValueOrDefault(defName),
|
||||
DefKind.AffinityRules => Affinity.GetValueOrDefault(defName),
|
||||
DefKind.Event => Events.GetValueOrDefault(defName),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -246,6 +251,7 @@ public sealed class DefCatalog
|
||||
TopicDef => DefKind.Topic,
|
||||
OrientationDef => DefKind.Orientation,
|
||||
AffinityRulesDef => DefKind.AffinityRules,
|
||||
EventDef => DefKind.Event,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(def)),
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ public enum DefKind
|
||||
Topic,
|
||||
Orientation,
|
||||
AffinityRules,
|
||||
Event,
|
||||
}
|
||||
|
||||
/// <summary>Shared JSONC fields. Kind comes from the folder under <c>defs/</c>, not from the file.</summary>
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
namespace HSchool.Content;
|
||||
|
||||
internal static class EventDefValidator
|
||||
{
|
||||
private static readonly HashSet<string> Severities = new(StringComparer.Ordinal)
|
||||
{
|
||||
EventSeverities.Info,
|
||||
EventSeverities.Warning,
|
||||
EventSeverities.Error,
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> Triggers = new(StringComparer.Ordinal)
|
||||
{
|
||||
EventTriggers.DayStart,
|
||||
EventTriggers.LessonStart,
|
||||
EventTriggers.GenerationFailed,
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> Actions = new(StringComparer.Ordinal)
|
||||
{
|
||||
EventActions.None,
|
||||
EventActions.GenerateImage,
|
||||
};
|
||||
|
||||
public static void Validate(DefCatalog catalog)
|
||||
{
|
||||
foreach (var def in catalog.Events.Values)
|
||||
{
|
||||
if (!Severities.Contains(def.Severity))
|
||||
{
|
||||
throw new ContentLoadException($"EventDef '{def.DefName}' has unknown severity '{def.Severity}'.");
|
||||
}
|
||||
|
||||
if (!Triggers.Contains(def.Trigger))
|
||||
{
|
||||
throw new ContentLoadException($"EventDef '{def.DefName}' has unknown trigger '{def.Trigger}'.");
|
||||
}
|
||||
|
||||
if (!Actions.Contains(def.Action))
|
||||
{
|
||||
throw new ContentLoadException($"EventDef '{def.DefName}' has unknown action '{def.Action}'.");
|
||||
}
|
||||
|
||||
if (def.TtlMs < 0)
|
||||
{
|
||||
throw new ContentLoadException($"EventDef '{def.DefName}' ttlMs cannot be negative.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
namespace HSchool.Content;
|
||||
|
||||
public static class EventSeverities
|
||||
{
|
||||
public const string Info = "info";
|
||||
public const string Warning = "warning";
|
||||
public const string Error = "error";
|
||||
}
|
||||
|
||||
public static class EventTriggers
|
||||
{
|
||||
public const string DayStart = "dayStart";
|
||||
public const string LessonStart = "lessonStart";
|
||||
public const string GenerationFailed = "generationFailed";
|
||||
}
|
||||
|
||||
public static class EventActions
|
||||
{
|
||||
public const string None = "none";
|
||||
public const string GenerateImage = "generateImage";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fact the world can raise. Systems emit a trigger; the worker matches this def and builds a notice.
|
||||
/// </summary>
|
||||
public sealed class EventDef : Def
|
||||
{
|
||||
public string Severity { get; init; } = EventSeverities.Info;
|
||||
|
||||
public bool Pause { get; init; }
|
||||
|
||||
/// <summary>Client toast lifetime in milliseconds. Zero means it stays until dismiss.</summary>
|
||||
public int TtlMs { get; init; }
|
||||
|
||||
public string Trigger { get; init; } = "";
|
||||
|
||||
public string Action { get; init; } = EventActions.None;
|
||||
}
|
||||
@@ -138,6 +138,9 @@ internal static class PackPaths
|
||||
case "affinity":
|
||||
kind = DefKind.AffinityRules;
|
||||
return true;
|
||||
case "events":
|
||||
kind = DefKind.Event;
|
||||
return true;
|
||||
default:
|
||||
kind = default;
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user