using Content.Shared.Destructible.Thresholds;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.GameTicking.Components;
///
/// Component attached to all gamerule entities.
/// Used to both track the entity as well as store basic data
///
[RegisterComponent, EntityCategory("GameRules")]
public sealed partial class GameRuleComponent : Component
{
///
/// Game time when game rule was activated
///
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan ActivatedAt;
///
/// The minimum amount of players needed for this game rule.
///
[DataField]
public int MinPlayers;
///
/// If true, this rule not having enough players will cancel the preset selection.
/// If false, it will simply not run silently.
///
[DataField]
public bool CancelPresetOnTooFewPlayers = true;
///
/// Marks a gamerule as "Silent" meaning that it will run and then proceed to delete itself without logging.
/// This WILL throw a debug assert if it still exists when it's supposed to start!
///
[DataField]
public bool Silent;
///
/// A delay for when the rule the is started and when the starting logic actually runs.
///
[DataField]
public MinMax? Delay;
}
///
/// Raised when a rule is added but hasn't formally begun yet.
/// Good for announcing station events and other such things.
///
[ByRefEvent]
public readonly record struct GameRuleAddedEvent(Entity Rule);
///
/// Raised when the rule actually begins.
/// Player-facing logic should begin here.
///
[ByRefEvent]
public readonly record struct GameRuleStartedEvent(Entity Rule, EntProtoId? RuleId);
///
/// Raised when the rule ends.
/// Do cleanup and other such things here.
///
[ByRefEvent]
public readonly record struct GameRuleEndedEvent(EntityUid Rule);
///
/// A simple struct to keep track of the Lifespan of a Gamerule in an organized fashion.
///
/// Time that this game rule was added, or started
/// EntityUid of the game rule
/// Current lifetime of the game rule.
[Access(typeof(GameTicker))]
public record struct GameRule(TimeSpan StartTime, EntityUid Uid, GameRuleLifeStage LifeStage = GameRuleLifeStage.Added) : IComparable, IComparable
{
///
/// The time that this rule has started, or was added if it hasn't started yet!
///
public TimeSpan StartTime { get; private set; } = StartTime;
///
/// EntityUid for this GameRule, it's cheaper memory wise to store an int over the whole ass ProtoId, which is available through MetaDataComp lookup...
///
public readonly EntityUid Uid = Uid;
///
/// The time that this rule has started, or was added if it hasn't started yet!
///
public GameRuleLifeStage LifeStage { get; private set; } = LifeStage;
///
/// Marks that this GameRule has been started.
///
/// Timespan which we started the rule.
/// True if the game rule successfully started, false if was already started or ended.
public bool StartRule(TimeSpan time)
{
if (LifeStage > GameRuleLifeStage.Added)
return false;
LifeStage = GameRuleLifeStage.Started;
StartTime = time;
return true;
}
///
/// Marks that this GameRule has ended.
///
public bool EndRule()
{
if (LifeStage == GameRuleLifeStage.Ended)
return false;
LifeStage = GameRuleLifeStage.Ended;
return true;
}
public int CompareTo(GameRule other)
{
return CompareTo(other.LifeStage);
}
public int CompareTo(GameRuleLifeStage other)
{
return LifeStage.CompareTo(other);
}
public static implicit operator GameRule((TimeSpan Time, EntityUid Rule) tuple)
{
return new GameRule(tuple.Time, tuple.Rule);
}
public static implicit operator GameRule((TimeSpan Time, EntityUid Rule, GameRuleLifeStage Stage) tuple)
{
return new GameRule(tuple.Time, tuple.Rule, tuple.Stage);
}
public readonly void Deconstruct(out TimeSpan time, out EntityUid rule)
{
time = StartTime;
rule = Uid;
}
public readonly void Deconstruct(out TimeSpan time, out EntityUid rule, out GameRuleLifeStage stage)
{
time = StartTime;
rule = Uid;
stage = LifeStage;
}
}
public enum GameRuleLifeStage : byte
{
Added = 0,
Started = 1,
Ended = 2,
}