Skip to content

Commit

Permalink
Event scheduler caching (LaryNevesPR#2)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
ewokswagger authored Nov 12, 2024
1 parent e53253f commit bf9cd26
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 15 deletions.
26 changes: 26 additions & 0 deletions Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ protected override void Started(EntityUid uid, BasicStationEventSchedulerCompone
{
// 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,
Expand Down Expand Up @@ -77,6 +85,24 @@ public override void Update(float frameTime)
}
// 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);
}
Expand Down
55 changes: 42 additions & 13 deletions Content.Server/StationEvents/EventManagerSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,23 @@ public void RunRandomEvent()
/// </summary>
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;
Expand All @@ -90,17 +97,24 @@ public bool TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, out s

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<EntityPrototype, StationEventComponent> limitedEvents)
{
return TryBuildLimitedEvents(limitedEventsTable, out limitedEvents, null);
}
// DeltaV - end overloaded for backwards compatiblity

/// <summary>
/// Returns true if the provided EntityTableSelector gives at least one prototype with a StationEvent comp.
/// </summary>
public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary<EntityPrototype, StationEventComponent> limitedEvents)
public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary<EntityPrototype, StationEventComponent> limitedEvents, TimeSpan? eventRunTime) // DeltaV - Add a time overide
{
limitedEvents = new Dictionary<EntityPrototype, StationEventComponent>();

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!");
Expand Down Expand Up @@ -186,23 +200,38 @@ public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Di
return null;
}

// DeltaV - overloaded for backwards compatiblity
public Dictionary<EntityPrototype, StationEventComponent> AvailableEvents(
bool ignoreEarliestStart = false,
int? playerCountOverride = 100,
TimeSpan? currentTimeOverride = null)
{
return AvailableEvents(null, ignoreEarliestStart, playerCountOverride, currentTimeOverride);
}
// DeltaV - end overloaded for backwards compatiblity

/// <summary>
/// Gets the events that have met their player count, time-until start, etc.
/// </summary>
/// <param name="playerCountOverride">Override for player count, if using this to simulate events rather than in an actual round.</param>
/// <param name="currentTimeOverride">Override for round time, if using this to simulate events rather than in an actual round.</param>
/// <returns></returns>
public Dictionary<EntityPrototype, StationEventComponent> 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<EntityPrototype, StationEventComponent>();

Expand Down
30 changes: 30 additions & 0 deletions Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs
Original file line number Diff line number Diff line change
@@ -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<RampingStationEventSchedulerComponent>
{
[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

/// <summary>
/// Returns the ChaosModifier which increases as round time increases to a point.
Expand All @@ -36,6 +40,14 @@ protected override void Started(EntityUid uid, RampingStationEventSchedulerCompo
component.StartingChaos = component.MaxChaos / 10;

PickNextEventTime(uid, component);

// 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
}

public override void Update(float frameTime)
Expand All @@ -57,6 +69,24 @@ public override void Update(float frameTime)
continue;
}

// 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.
{
PickNextEventTime(uid, scheduler);
TimeSpan nextEventTime = _timing.CurTime + TimeSpan.FromSeconds(scheduler.TimeUntilNextEvent);
if (!_event.TryGenerateRandomEvent(scheduler.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

PickNextEventTime(uid, scheduler);
_event.RunRandomEvent(scheduler.ScheduledGameRules);
}
Expand Down
2 changes: 1 addition & 1 deletion Content.Shared/DeltaV/StationEvents/NextEventComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ public sealed partial class NextEventComponent : Component
/// Round time of the scheduler's next station event.
/// </summary>
[DataField]
public float NextEventTime;
public TimeSpan NextEventTime;
}
2 changes: 1 addition & 1 deletion Content.Shared/DeltaV/StationEvents/NextEventSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public sealed partial class NextEventSystem : EntitySystem
/// <summary>
/// Updates the NextEventComponent with the provided id and time and returns the previously stored id.
/// </summary>
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;
Expand Down
4 changes: 4 additions & 0 deletions Resources/Prototypes/GameRules/meteorswarms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
parent: BaseGameRule
id: MeteorSwarmScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 600 # 10 min
Expand All @@ -68,6 +69,7 @@
parent: BaseGameRule
id: MeteorSwarmMildScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 600 # 10 min
Expand All @@ -82,6 +84,7 @@
parent: BaseGameRule
id: KesslerSyndromeScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: RampingStationEventScheduler
scheduledGameRules: !type:NestedSelector
Expand All @@ -94,6 +97,7 @@
id: GameRuleMeteorSwarm
abstract: true
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: StationEvent
reoccurrenceDelay: 1
Expand Down
1 change: 1 addition & 0 deletions Resources/Prototypes/GameRules/roundstart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@
id: RampingStationEventScheduler
parent: BaseGameRule
components:
- type: NextEvent # DeltaV: Queue Event
- type: RampingStationEventScheduler
averageChaos: 4.5 # DeltaV
averageEndTime: 180 # DeltaV
Expand Down

0 comments on commit bf9cd26

Please sign in to comment.