using Content.Shared.GameTicking.Components; using Robust.Shared.Random; using Robust.Shared.Timing; namespace Content.Shared.GameTicking.Rules; public abstract partial class GameRuleSystem : EntitySystem where T : IComponent { [Dependency] protected IGameTiming Timing = default!; [Dependency] protected IRobustRandom RobustRandom = default!; [Dependency] protected GameTicker GameTicker = default!; [Dependency] protected EntityQuery RuleQuery = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnGameRuleAdded); SubscribeLocalEvent(OnGameRuleStarted); SubscribeLocalEvent(OnGameRuleEnded); } private void OnGameRuleAdded(Entity entity, ref GameRuleAddedEvent args) { Added((entity, entity, args.Rule), ref args); } private void OnGameRuleStarted(Entity entity, ref GameRuleStartedEvent args) { Started((entity, entity, args.Rule), ref args); } private void OnGameRuleEnded(Entity entity, ref GameRuleEndedEvent args) { Ended((entity, entity), ref args); } [SubscribeLocalEvent] private void OnRoundEndTextAppend(ref RoundEndTextAppendEvent ev) { // We don't query GameRuleComponent since the rule may have ended! var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp)) { AppendRoundEndText((uid, comp), ref ev); } } /// /// Called when the gamerule is added. /// [Obsolete("Use Entity version instead")] protected virtual void Added(EntityUid uid, T component, GameRuleComponent gameRule, GameRuleAddedEvent args) { } /// /// Called when the gamerule is added. /// protected virtual void Added(Entity rule, ref GameRuleAddedEvent args) { #pragma warning disable CS0618 // maintaining compatibility behaviour, remove with obsolete Added above Added(rule.Owner, rule.Comp1, rule.Comp2, args); #pragma warning restore CS0618 } /// /// Called when the gamerule begins. /// [Obsolete("Use Entity version instead")] protected virtual void Started(EntityUid uid, T component, GameRuleComponent gameRule, GameRuleStartedEvent args) { } /// /// Called when the gamerule begins. /// protected virtual void Started(Entity rule, ref GameRuleStartedEvent args) { #pragma warning disable CS0618 // maintaining compatibility behaviour, remove with obsolete Started above Started(rule.Owner, rule.Comp1, rule.Comp2, args); #pragma warning restore CS0618 } /// /// Called when the gamerule is added /// protected virtual void Ended(Entity rule, ref GameRuleEndedEvent args) { } /// w /// Called at the end of a round when text needs to be added for a game rule. /// protected virtual void AppendRoundEndText(Entity rule, ref RoundEndTextAppendEvent args) { } /// /// Called on an active gamerule entity in the Update function /// protected virtual void ActiveTick(EntityUid uid, T component, GameRuleComponent gameRule, float frameTime) { } // TODO: We probably should move this to its own rule system that way we aren't doing an Enumerator for EVERY SINGLE GameRule. // TODO: Or have GameTicker query over all GameRules once and then raise to each one :P // TODO: Either way something that isn't this... public override void Update(float frameTime) { base.Update(frameTime); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp1, out _, out var comp2)) { ActiveTick(uid, comp1, comp2, frameTime); } } }