From bf9cd26ed4761b2e47f0259d576d15526844793b Mon Sep 17 00:00:00 2001 From: SolStar <44028047+ewokswagger@users.noreply.github.com> Date: Tue, 12 Nov 2024 18:04:50 -0500 Subject: [PATCH] Event scheduler caching (#2) * Check for schedulers NextEventComponent * Seperate gernateing event to its own method * Add NextEventSystem and use in BasicStationEventSchedulerSystem * Format code * Add nextEvent time perdiction * Use RunTime instead of float minutes * Bug fixes * Add NextEvent to Ramping and Meteors * Fix timing on BasticStationEvents * initialize NextEventComponent when created --------- Signed-off-by: SolStar <44028047+ewokswagger@users.noreply.github.com> --- .../BasicStationEventSchedulerSystem.cs | 26 +++++++++ .../StationEvents/EventManagerSystem.cs | 55 ++++++++++++++----- .../RampingStationEventSchedulerSystem.cs | 30 ++++++++++ .../StationEvents/NextEventComponent.cs | 2 +- .../DeltaV/StationEvents/NextEventSystem.cs | 2 +- .../Prototypes/GameRules/meteorswarms.yml | 4 ++ Resources/Prototypes/GameRules/roundstart.yml | 1 + 7 files changed, 105 insertions(+), 15 deletions(-) diff --git a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs index 4f69a708e5..a74b8389fd 100644 --- a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs +++ b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs @@ -33,6 +33,14 @@ namespace Content.Server.StationEvents { // A little starting variance so schedulers dont all proc at once. component.TimeUntilNextEvent = RobustRandom.NextFloat(component.MinimumTimeUntilFirstEvent, component.MinimumTimeUntilFirstEvent + 120); + + // DeltaV - end init NextEventComp + NextEventComponent? nextEventComponent = null; + if (Resolve(uid, ref nextEventComponent, false) + && _event.TryGenerateRandomEvent(component.ScheduledGameRules, out string? firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent)) + && firstEvent != null) + _next.UpdateNextEvent(nextEventComponent, firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent)); + // DeltaV - end init NextEventComp } protected override void Ended(EntityUid uid, BasicStationEventSchedulerComponent component, GameRuleComponent gameRule, @@ -77,6 +85,24 @@ namespace Content.Server.StationEvents } // DeltaV end events using NextEventComponent + // DeltaV events using NextEventComponent + NextEventComponent? nextEventComponent = null; + + if (Resolve(uid, ref nextEventComponent, false)) // If there is a nextEventComponent use the stashed event instead of running it directly. + { + ResetTimer(eventScheduler); + TimeSpan nextEventTime = _timing.CurTime + TimeSpan.FromSeconds(eventScheduler.TimeUntilNextEvent); + if (!_event.TryGenerateRandomEvent(eventScheduler.ScheduledGameRules, out string? generatedEvent, nextEventTime) || generatedEvent == null) + continue; + // Cycle the stashed event with the new generated event and time. + string storedEvent= _next.UpdateNextEvent(nextEventComponent, generatedEvent, nextEventTime); + if (storedEvent == null || storedEvent == string.Empty) //If there was no stored event don't try to run it. + continue; + GameTicker.AddGameRule(storedEvent); + continue; + } + // DeltaV end events using NextEventComponent + _event.RunRandomEvent(eventScheduler.ScheduledGameRules); ResetTimer(eventScheduler); } diff --git a/Content.Server/StationEvents/EventManagerSystem.cs b/Content.Server/StationEvents/EventManagerSystem.cs index fbe069509d..215396d1bb 100644 --- a/Content.Server/StationEvents/EventManagerSystem.cs +++ b/Content.Server/StationEvents/EventManagerSystem.cs @@ -58,16 +58,23 @@ public sealed class EventManagerSystem : EntitySystem /// public void RunRandomEvent(EntityTableSelector limitedEventsTable) { - if(TryGenerateRandomEvent(limitedEventsTable, out string? randomLimitedEvent) && randomLimitedEvent != null) // DeltaV seperated into own method + if(TryGenerateRandomEvent(limitedEventsTable, out string? randomLimitedEvent) && randomLimitedEvent != null) // DeltaV - seperated into own method GameTicker.AddGameRule(randomLimitedEvent); } - // DeltaV seperate event generation method + // DeltaV - overloaded for backwards compatiblity public bool TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, out string? randomLimitedEvent) + { + return TryGenerateRandomEvent(limitedEventsTable, out randomLimitedEvent, null); + } + // DeltaV - end overloaded for backwards compatiblity + + // DeltaV - seperate event generation method + public bool TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, out string? randomLimitedEvent, TimeSpan? eventRunTime) // Event time checks compared to eventRunTime + // unless its null in which case current time is used { randomLimitedEvent = null; - // Snippet from upstreams RunRandomEvent - if (!TryBuildLimitedEvents(limitedEventsTable, out var limitedEvents)) + if (!TryBuildLimitedEvents(limitedEventsTable, out var limitedEvents, eventRunTime)) { Log.Warning("Provided event table could not build dict!"); return false; @@ -90,17 +97,24 @@ public sealed class EventManagerSystem : EntitySystem return true; } - // DeltaV end seperate event generation method + // DeltaV - end seperate event generation method + + // DeltaV - overloaded for backwards compatiblity + public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary limitedEvents) + { + return TryBuildLimitedEvents(limitedEventsTable, out limitedEvents, null); + } + // DeltaV - end overloaded for backwards compatiblity /// /// Returns true if the provided EntityTableSelector gives at least one prototype with a StationEvent comp. /// - public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary limitedEvents) + public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary limitedEvents, TimeSpan? eventRunTime) // DeltaV - Add a time overide { limitedEvents = new Dictionary(); - var availableEvents = AvailableEvents(); // handles the player counts and individual event restrictions - + var availableEvents = AvailableEvents(eventRunTime); // handles the player counts and individual event restrictions + // DeltaV - Overide time for stashing events if (availableEvents.Count == 0) { Log.Warning("No events were available to run!"); @@ -186,6 +200,16 @@ public sealed class EventManagerSystem : EntitySystem return null; } + // DeltaV - overloaded for backwards compatiblity + public Dictionary AvailableEvents( + bool ignoreEarliestStart = false, + int? playerCountOverride = 100, + TimeSpan? currentTimeOverride = null) + { + return AvailableEvents(null, ignoreEarliestStart, playerCountOverride, currentTimeOverride); + } + // DeltaV - end overloaded for backwards compatiblity + /// /// Gets the events that have met their player count, time-until start, etc. /// @@ -193,16 +217,21 @@ public sealed class EventManagerSystem : EntitySystem /// Override for round time, if using this to simulate events rather than in an actual round. /// public Dictionary AvailableEvents( - bool ignoreEarliestStart = true, + TimeSpan? eventRunTime, + bool ignoreEarliestStart = false, int? playerCountOverride = 100, - TimeSpan? currentTimeOverride = null) + TimeSpan? currentTimeOverride = null + ) { var playerCount = playerCountOverride ?? _playerManager.PlayerCount; // playerCount does a lock so we'll just keep the variable here - var currentTime = currentTimeOverride ?? (!ignoreEarliestStart - ? GameTicker.RoundDuration() - : TimeSpan.Zero); + var currentTime = currentTimeOverride ?? ( + (!ignoreEarliestStart + ? eventRunTime // DeltaV - Use eventRunTime instead of RoundDuration if provided + ?? GameTicker.RoundDuration() + : TimeSpan.Zero) + ); var result = new Dictionary(); diff --git a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs index a5dbe102ca..8a119bd14d 100644 --- a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs +++ b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs @@ -1,16 +1,20 @@ using Content.Server.GameTicking; using Content.Server.GameTicking.Rules; using Content.Server.StationEvents.Components; +using Content.Shared.DeltaV.StationEvents; using Content.Shared.GameTicking.Components; using Robust.Shared.Random; +using Robust.Shared.Timing; namespace Content.Server.StationEvents; public sealed class RampingStationEventSchedulerSystem : GameRuleSystem { + [Dependency] private readonly IGameTiming _timing = default!; // DeltaV [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly EventManagerSystem _event = default!; [Dependency] private readonly GameTicker _gameTicker = default!; + [Dependency] private readonly NextEventSystem _next = default!; // DeltaV /// /// Returns the ChaosModifier which increases as round time increases to a point. @@ -36,6 +40,14 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem [DataField] - public float NextEventTime; + public TimeSpan NextEventTime; } diff --git a/Content.Shared/DeltaV/StationEvents/NextEventSystem.cs b/Content.Shared/DeltaV/StationEvents/NextEventSystem.cs index 5fdad15457..bd7c8d17e6 100644 --- a/Content.Shared/DeltaV/StationEvents/NextEventSystem.cs +++ b/Content.Shared/DeltaV/StationEvents/NextEventSystem.cs @@ -7,7 +7,7 @@ public sealed partial class NextEventSystem : EntitySystem /// /// Updates the NextEventComponent with the provided id and time and returns the previously stored id. /// - public EntProtoId UpdateNextEvent(NextEventComponent component, EntProtoId newEventId, float newEventTime) + public EntProtoId UpdateNextEvent(NextEventComponent component, EntProtoId newEventId, TimeSpan newEventTime) { EntProtoId oldEventId = component.NextEventId; // Store components current NextEventId for return component.NextEventId = newEventId; diff --git a/Resources/Prototypes/GameRules/meteorswarms.yml b/Resources/Prototypes/GameRules/meteorswarms.yml index 95f9985b6a..61ae431289 100644 --- a/Resources/Prototypes/GameRules/meteorswarms.yml +++ b/Resources/Prototypes/GameRules/meteorswarms.yml @@ -55,6 +55,7 @@ parent: BaseGameRule id: MeteorSwarmScheduler components: + - type: NextEvent # DeltaV: Queue Event - type: GameRule - type: BasicStationEventScheduler minimumTimeUntilFirstEvent: 600 # 10 min @@ -68,6 +69,7 @@ parent: BaseGameRule id: MeteorSwarmMildScheduler components: + - type: NextEvent # DeltaV: Queue Event - type: GameRule - type: BasicStationEventScheduler minimumTimeUntilFirstEvent: 600 # 10 min @@ -82,6 +84,7 @@ parent: BaseGameRule id: KesslerSyndromeScheduler components: + - type: NextEvent # DeltaV: Queue Event - type: GameRule - type: RampingStationEventScheduler scheduledGameRules: !type:NestedSelector @@ -94,6 +97,7 @@ id: GameRuleMeteorSwarm abstract: true components: + - type: NextEvent # DeltaV: Queue Event - type: GameRule - type: StationEvent reoccurrenceDelay: 1 diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index 688b399d11..56d1b6e225 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -309,6 +309,7 @@ id: RampingStationEventScheduler parent: BaseGameRule components: + - type: NextEvent # DeltaV: Queue Event - type: RampingStationEventScheduler averageChaos: 4.5 # DeltaV averageEndTime: 180 # DeltaV