Refactor Advertise System (#19669)

* Refactor Advertise System

* Added interval checks

* More stuff
This commit is contained in:
Wrexbe (Josh)
2023-09-22 08:46:25 -07:00
committed by GitHub
parent b765cb7b85
commit 9e1a9dd6df

View File

@@ -1,8 +1,6 @@
using Content.Server.Advertisements; using Content.Server.Advertisements;
using Content.Server.Chat;
using Content.Server.Chat.Systems; using Content.Server.Chat.Systems;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.VendingMachines;
using Content.Shared.VendingMachines; using Content.Shared.VendingMachines;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
@@ -17,9 +15,15 @@ namespace Content.Server.Advertise
[Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly ChatSystem _chat = default!;
private const float UpdateTimer = 5f; /// <summary>
/// The maximum amount of time between checking if advertisements should be displayed
/// </summary>
private readonly TimeSpan _maximumNextCheckDuration = TimeSpan.FromSeconds(15);
private float _timer = 0f; /// <summary>
/// The next time the game will check if advertisements should be displayed
/// </summary>
private TimeSpan _nextCheckTime = TimeSpan.MaxValue;
public override void Initialize() public override void Initialize()
{ {
@@ -28,11 +32,14 @@ namespace Content.Server.Advertise
SubscribeLocalEvent<ApcPowerReceiverComponent, AdvertiseEnableChangeAttemptEvent>(OnPowerReceiverEnableChangeAttempt); SubscribeLocalEvent<ApcPowerReceiverComponent, AdvertiseEnableChangeAttemptEvent>(OnPowerReceiverEnableChangeAttempt);
SubscribeLocalEvent<VendingMachineComponent, AdvertiseEnableChangeAttemptEvent>(OnVendingEnableChangeAttempt); SubscribeLocalEvent<VendingMachineComponent, AdvertiseEnableChangeAttemptEvent>(OnVendingEnableChangeAttempt);
// The component inits will lower this.
_nextCheckTime = TimeSpan.MaxValue;
} }
private void OnComponentInit(EntityUid uid, AdvertiseComponent advertise, ComponentInit args) private void OnComponentInit(EntityUid uid, AdvertiseComponent advertise, ComponentInit args)
{ {
RefreshTimer(uid, true, advertise); RefreshTimer(uid, advertise);
} }
private void OnPowerChanged(EntityUid uid, AdvertiseComponent advertise, ref PowerChangedEvent args) private void OnPowerChanged(EntityUid uid, AdvertiseComponent advertise, ref PowerChangedEvent args)
@@ -40,94 +47,97 @@ namespace Content.Server.Advertise
SetEnabled(uid, args.Powered, advertise); SetEnabled(uid, args.Powered, advertise);
} }
public void RefreshTimer(EntityUid uid, bool minimumBound = true, AdvertiseComponent? advertise = null) public void RefreshTimer(EntityUid uid, AdvertiseComponent? advertise = null)
{ {
if (!Resolve(uid, ref advertise)) if (!Resolve(uid, ref advertise))
return; return;
var minWait = Math.Max(1, advertise.MinimumWait); if (!advertise.Enabled)
var maxWait = Math.Max(minWait, advertise.MaximumWait); return;
var waitSeconds = minimumBound ? _random.Next(minWait, maxWait) : _random.Next(maxWait); var minDuration = Math.Max(1, advertise.MinimumWait);
advertise.NextAdvertisementTime = _gameTiming.CurTime.Add(TimeSpan.FromSeconds(waitSeconds)); var maxDuration = Math.Max(minDuration, advertise.MaximumWait);
var waitDuration = TimeSpan.FromSeconds(_random.Next(minDuration, maxDuration));
var nextTime = _gameTiming.CurTime + waitDuration;
advertise.NextAdvertisementTime = nextTime;
_nextCheckTime = MathHelper.Min(nextTime, _nextCheckTime);
} }
public void SayAdvertisement(EntityUid uid, bool refresh = true, AdvertiseComponent? advertise = null) public void SayAdvertisement(EntityUid uid, AdvertiseComponent? advertise = null)
{ {
if (!Resolve(uid, ref advertise)) if (!Resolve(uid, ref advertise))
return; return;
if (_prototypeManager.TryIndex(advertise.PackPrototypeId, out AdvertisementsPackPrototype? advertisements)) if (_prototypeManager.TryIndex(advertise.PackPrototypeId, out AdvertisementsPackPrototype? advertisements))
_chat.TrySendInGameICMessage(advertise.Owner, Loc.GetString(_random.Pick(advertisements.Advertisements)), InGameICChatType.Speak, true); _chat.TrySendInGameICMessage(uid, Loc.GetString(_random.Pick(advertisements.Advertisements)), InGameICChatType.Speak, true);
if(refresh)
RefreshTimer(uid, true, advertise);
} }
public void SetEnabled(EntityUid uid, bool enabled, AdvertiseComponent? advertise = null) public void SetEnabled(EntityUid uid, bool enable, AdvertiseComponent? advertise = null)
{ {
if (!Resolve(uid, ref advertise)) if (!Resolve(uid, ref advertise))
return; return;
var attemptEvent = new AdvertiseEnableChangeAttemptEvent(enabled, advertise.Enabled); if (advertise.Enabled == enable)
RaiseLocalEvent(uid, attemptEvent, false); return;
var attemptEvent = new AdvertiseEnableChangeAttemptEvent(enable);
RaiseLocalEvent(uid, attemptEvent);
if (attemptEvent.Cancelled) if (attemptEvent.Cancelled)
return; return;
if(enabled) advertise.Enabled = enable;
RefreshTimer(uid, !advertise.Enabled, advertise); RefreshTimer(uid, advertise);
advertise.Enabled = enabled;
} }
private void OnPowerReceiverEnableChangeAttempt(EntityUid uid, ApcPowerReceiverComponent component, AdvertiseEnableChangeAttemptEvent args) private static void OnPowerReceiverEnableChangeAttempt(EntityUid uid, ApcPowerReceiverComponent component, AdvertiseEnableChangeAttemptEvent args)
{ {
if(args.NewState && !component.Powered) if(args.Enabling && !component.Powered)
args.Cancel(); args.Cancel();
} }
private void OnVendingEnableChangeAttempt(EntityUid uid, VendingMachineComponent component, AdvertiseEnableChangeAttemptEvent args) private static void OnVendingEnableChangeAttempt(EntityUid uid, VendingMachineComponent component, AdvertiseEnableChangeAttemptEvent args)
{ {
// TODO: Improve this... if(args.Enabling && component.Broken)
if(args.NewState && component.Broken)
args.Cancel(); args.Cancel();
} }
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
_timer += frameTime; var curTime = _gameTiming.CurTime;
if (_nextCheckTime > curTime)
if (_timer < UpdateTimer)
return; return;
_timer -= UpdateTimer; _nextCheckTime = curTime + _maximumNextCheckDuration;
var curTime = _gameTiming.CurTime; var query = EntityQueryEnumerator<AdvertiseComponent>();
while (query.MoveNext(out var uid, out var advert))
foreach (var advertise in EntityManager.EntityQuery<AdvertiseComponent>())
{ {
if (!advertise.Enabled) if (!advert.Enabled)
continue; continue;
// If it's still not time for the advertisement, do nothing. // If this isn't advertising yet
if (advertise.NextAdvertisementTime > curTime) if (advert.NextAdvertisementTime > curTime)
{
_nextCheckTime = MathHelper.Min(advert.NextAdvertisementTime, _nextCheckTime);
continue; continue;
}
SayAdvertisement(advertise.Owner, true, advertise); SayAdvertisement(uid, advert);
RefreshTimer(uid, advert);
} }
} }
} }
public sealed class AdvertiseEnableChangeAttemptEvent : CancellableEntityEventArgs public sealed class AdvertiseEnableChangeAttemptEvent : CancellableEntityEventArgs
{ {
public bool NewState { get; } public bool Enabling { get; }
public bool OldState { get; }
public AdvertiseEnableChangeAttemptEvent(bool newState, bool oldEnabledState) public AdvertiseEnableChangeAttemptEvent(bool enabling)
{ {
NewState = newState; Enabling = enabling;
OldState = oldEnabledState;
} }
} }
} }