diff --git a/Content.Server/GameTicking/Rules/Configurations/GameRuleConfiguration.cs b/Content.Server/GameTicking/Rules/Configurations/GameRuleConfiguration.cs new file mode 100644 index 0000000000..600cc9d54e --- /dev/null +++ b/Content.Server/GameTicking/Rules/Configurations/GameRuleConfiguration.cs @@ -0,0 +1,13 @@ +namespace Content.Server.GameTicking.Rules.Configurations; + +/// +/// Configures a game rule, providing information like what maps to use or how long to run. +/// +[ImplicitDataDefinitionForInheritors] +public abstract class GameRuleConfiguration +{ + /// + /// The game rule this configuration is intended for. + /// + public abstract string Id { get; } +} diff --git a/Content.Server/GameTicking/Rules/Configurations/GenericGameRuleConfiguration.cs b/Content.Server/GameTicking/Rules/Configurations/GenericGameRuleConfiguration.cs new file mode 100644 index 0000000000..1db383c169 --- /dev/null +++ b/Content.Server/GameTicking/Rules/Configurations/GenericGameRuleConfiguration.cs @@ -0,0 +1,14 @@ +using JetBrains.Annotations; + +namespace Content.Server.GameTicking.Rules.Configurations; + +/// +/// A generic configuration, for game rules that don't have special config data. +/// +[UsedImplicitly] +public sealed class GenericGameRuleConfiguration : GameRuleConfiguration +{ + [DataField("id", required: true)] + private string _id = default!; + public override string Id => _id; +} diff --git a/Content.Server/GameTicking/Rules/Configurations/InactivityGameRuleConfiguration.cs b/Content.Server/GameTicking/Rules/Configurations/InactivityGameRuleConfiguration.cs new file mode 100644 index 0000000000..bc60d77adb --- /dev/null +++ b/Content.Server/GameTicking/Rules/Configurations/InactivityGameRuleConfiguration.cs @@ -0,0 +1,17 @@ +using JetBrains.Annotations; + +namespace Content.Server.GameTicking.Rules.Configurations; + +/// +/// Configures the game rule. +/// +[UsedImplicitly] +public sealed class InactivityGameRuleConfiguration : GameRuleConfiguration +{ + public override string Id => "InactivityTimeRestart"; // The value for this in the system isn't static and can't be made static. RIP. + + [DataField("inactivityMaxTime", required: true)] + public TimeSpan InactivityMaxTime { get; } + [DataField("roundEndDelay", required: true)] + public TimeSpan RoundEndDelay { get; } +} diff --git a/Content.Server/GameTicking/Rules/Configurations/MaxTimeRestartRuleConfiguration.cs b/Content.Server/GameTicking/Rules/Configurations/MaxTimeRestartRuleConfiguration.cs new file mode 100644 index 0000000000..d4cd3f39b0 --- /dev/null +++ b/Content.Server/GameTicking/Rules/Configurations/MaxTimeRestartRuleConfiguration.cs @@ -0,0 +1,17 @@ +using JetBrains.Annotations; + +namespace Content.Server.GameTicking.Rules.Configurations; + +/// +/// Configures the game rule. +/// +[UsedImplicitly] +public sealed class MaxTimeRestartRuleConfiguration : GameRuleConfiguration +{ + public override string Id => "MaxTimeRestart"; // The value for this in the system isn't static and can't be made static. RIP. + + [DataField("roundMaxTime", required: true)] + public TimeSpan RoundMaxTime { get; } + [DataField("roundEndDelay", required: true)] + public TimeSpan RoundEndDelay { get; } +} diff --git a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs index cda80abd0d..78ed1e25f0 100644 --- a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs @@ -1,4 +1,5 @@ using Content.Server.Chat.Managers; +using Content.Server.GameTicking.Rules.Configurations; using Content.Shared.CCVar; using Content.Shared.Damage; using Content.Shared.MobState.Components; @@ -33,14 +34,14 @@ public sealed class DeathMatchRuleSystem : GameRuleSystem SubscribeLocalEvent(OnHealthChanged); } - public override void Started() + public override void Started(GameRuleConfiguration _) { _chatManager.DispatchServerAnnouncement(Loc.GetString("rule-death-match-added-announcement")); _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; } - public override void Ended() + public override void Ended(GameRuleConfiguration _) { _deadCheckTimer = null; _restartTimer = null; diff --git a/Content.Server/GameTicking/Rules/GameRulePrototype.cs b/Content.Server/GameTicking/Rules/GameRulePrototype.cs index 7ef4e283cc..d48eb1333a 100644 --- a/Content.Server/GameTicking/Rules/GameRulePrototype.cs +++ b/Content.Server/GameTicking/Rules/GameRulePrototype.cs @@ -1,3 +1,4 @@ +using Content.Server.GameTicking.Rules.Configurations; using Robust.Shared.Prototypes; namespace Content.Server.GameTicking.Rules; @@ -5,6 +6,9 @@ namespace Content.Server.GameTicking.Rules; [Prototype("gameRule")] public sealed class GameRulePrototype : IPrototype { - [IdDataFieldAttribute] + [IdDataField] public string ID { get; } = default!; + + [DataField("config", required: true)] + public GameRuleConfiguration Configuration { get; } = default!; } diff --git a/Content.Server/GameTicking/Rules/GameRuleSystem.cs b/Content.Server/GameTicking/Rules/GameRuleSystem.cs index 3a5bb5bb1f..eba6a386b2 100644 --- a/Content.Server/GameTicking/Rules/GameRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/GameRuleSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.GameTicking.Rules.Configurations; using JetBrains.Annotations; namespace Content.Server.GameTicking.Rules; @@ -31,7 +32,7 @@ public abstract class GameRuleSystem : EntitySystem private void OnGameRuleAdded(GameRuleAddedEvent ev) { - if (ev.Rule.ID != Prototype) + if (ev.Rule.Configuration.Id != Prototype) return; Enabled = true; @@ -39,28 +40,28 @@ public abstract class GameRuleSystem : EntitySystem private void OnGameRuleStarted(GameRuleStartedEvent ev) { - if (ev.Rule.ID != Prototype) + if (ev.Rule.Configuration.Id != Prototype) return; - Started(); + Started(ev.Rule.Configuration); } private void OnGameRuleEnded(GameRuleEndedEvent ev) { - if (ev.Rule.ID != Prototype) + if (ev.Rule.Configuration.Id != Prototype) return; Enabled = false; - Ended(); + Ended(ev.Rule.Configuration); } /// /// Called when the game rule has been started.. /// - public abstract void Started(); + public abstract void Started(GameRuleConfiguration configuration); /// /// Called when the game rule has ended.. /// - public abstract void Ended(); + public abstract void Ended(GameRuleConfiguration configuration); } diff --git a/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs b/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs index 52e5970fac..4c76ddd0e1 100644 --- a/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs @@ -1,5 +1,6 @@ using System.Threading; using Content.Server.Chat.Managers; +using Content.Server.GameTicking.Rules.Configurations; using Robust.Server.Player; using Timer = Robust.Shared.Timing.Timer; @@ -24,12 +25,16 @@ public sealed class InactivityTimeRestartRuleSystem : GameRuleSystem SubscribeLocalEvent(RunLevelChanged); } - public override void Started() + public override void Started(GameRuleConfiguration config) { + if (config is not InactivityGameRuleConfiguration inactivityConfig) + return; + InactivityMaxTime = inactivityConfig.InactivityMaxTime; + RoundEndDelay = inactivityConfig.RoundEndDelay; _playerManager.PlayerStatusChanged += PlayerStatusChanged; } - public override void Ended() + public override void Ended(GameRuleConfiguration _) { _playerManager.PlayerStatusChanged -= PlayerStatusChanged; diff --git a/Content.Server/GameTicking/Rules/MaxTimeRestartRuleSystem.cs b/Content.Server/GameTicking/Rules/MaxTimeRestartRuleSystem.cs index 83ebffadfb..0574bc08c7 100644 --- a/Content.Server/GameTicking/Rules/MaxTimeRestartRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/MaxTimeRestartRuleSystem.cs @@ -1,5 +1,6 @@ using System.Threading; using Content.Server.Chat.Managers; +using Content.Server.GameTicking.Rules.Configurations; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.GameTicking.Rules; @@ -22,17 +23,19 @@ public sealed class MaxTimeRestartRuleSystem : GameRuleSystem SubscribeLocalEvent(RunLevelChanged); } - public override void Started() + public override void Started(GameRuleConfiguration config) { + if (config is not MaxTimeRestartRuleConfiguration maxTimeRestartConfig) + return; + RoundMaxTime = maxTimeRestartConfig.RoundMaxTime; + RoundEndDelay = maxTimeRestartConfig.RoundEndDelay; + if(GameTicker.RunLevel == GameRunLevel.InRound) RestartTimer(); } - public override void Ended() + public override void Ended(GameRuleConfiguration _) { - RoundMaxTime = TimeSpan.FromMinutes(5); - RoundEndDelay = TimeSpan.FromMinutes(10); - StopTimer(); } diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index 71225de70d..c3d5810925 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -1,6 +1,7 @@ using System.Linq; using Content.Server.CharacterAppearance.Components; using Content.Server.Chat.Managers; +using Content.Server.GameTicking.Rules.Configurations; using Content.Server.Nuke; using Content.Server.Players; using Content.Server.Roles; @@ -298,10 +299,10 @@ public sealed class NukeopsRuleSystem : GameRuleSystem } - public override void Started() + public override void Started(GameRuleConfiguration _) { _opsWon = false; } - public override void Ended() { } + public override void Ended(GameRuleConfiguration _) { } } diff --git a/Content.Server/GameTicking/Rules/SandboxRuleSystem.cs b/Content.Server/GameTicking/Rules/SandboxRuleSystem.cs index 46e541fa56..418f9ebf5c 100644 --- a/Content.Server/GameTicking/Rules/SandboxRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/SandboxRuleSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.GameTicking.Rules.Configurations; using Content.Server.Sandbox; namespace Content.Server.GameTicking.Rules; @@ -8,12 +9,12 @@ public sealed class SandboxRuleSystem : GameRuleSystem public override string Prototype => "Sandbox"; - public override void Started() + public override void Started(GameRuleConfiguration _) { _sandbox.IsSandboxEnabled = true; } - public override void Ended() + public override void Ended(GameRuleConfiguration _) { _sandbox.IsSandboxEnabled = false; } diff --git a/Content.Server/GameTicking/Rules/SecretRuleSystem.cs b/Content.Server/GameTicking/Rules/SecretRuleSystem.cs index cf820c2a73..838e8c0212 100644 --- a/Content.Server/GameTicking/Rules/SecretRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/SecretRuleSystem.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Server.GameTicking.Presets; +using Content.Server.GameTicking.Rules.Configurations; using Content.Shared.Random; using Content.Shared.Random.Helpers; using Robust.Shared.Prototypes; @@ -15,12 +16,12 @@ public sealed class SecretRuleSystem : GameRuleSystem public override string Prototype => "Secret"; - public override void Started() + public override void Started(GameRuleConfiguration _) { PickRule(); } - public override void Ended() + public override void Ended(GameRuleConfiguration _) { // noop // Preset should already handle it. diff --git a/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs b/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs index 2b272790b9..e2c666f739 100644 --- a/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Threading; using Content.Server.Chat.Managers; +using Content.Server.GameTicking.Rules.Configurations; using Content.Server.Players; using Content.Server.Roles; using Content.Server.Station.Components; @@ -202,7 +203,7 @@ public sealed class SuspicionRuleSystem : GameRuleSystem } } - public override void Started() + public override void Started(GameRuleConfiguration _) { _playerManager.PlayerStatusChanged += PlayerManagerOnPlayerStatusChanged; @@ -268,7 +269,7 @@ public sealed class SuspicionRuleSystem : GameRuleSystem Timer.SpawnRepeating(DeadCheckDelay, CheckWinConditions, _checkTimerCancel.Token); } - public override void Ended() + public override void Ended(GameRuleConfiguration _) { _doorSystem.AccessType = SharedDoorSystem.AccessTypes.Id; EndTime = null; diff --git a/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs index 2775a0ca43..c1934b5e6d 100644 --- a/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs @@ -1,6 +1,7 @@ using System.Linq; using Content.Server.Atmos.EntitySystems; using Content.Server.Chat.Managers; +using Content.Server.GameTicking.Rules.Configurations; using Content.Server.Hands.Components; using Content.Server.PDA; using Content.Server.Players; @@ -196,14 +197,14 @@ public sealed class TraitorDeathMatchRuleSystem : GameRuleSystem ev.AddLine(string.Join('\n', lines)); } - public override void Started() + public override void Started(GameRuleConfiguration _) { _restarter.RoundMaxTime = TimeSpan.FromMinutes(30); _restarter.RestartTimer(); _safeToEndRound = true; } - public override void Ended() + public override void Ended(GameRuleConfiguration _) { } diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index d47d5c012c..87f3e340d4 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Server.Chat.Managers; +using Content.Server.GameTicking.Rules.Configurations; using Content.Server.Objectives.Interfaces; using Content.Server.Players; using Content.Server.Roles; @@ -48,9 +49,9 @@ public sealed class TraitorRuleSystem : GameRuleSystem SubscribeLocalEvent(OnRoundEndText); } - public override void Started() {} + public override void Started(GameRuleConfiguration _) {} - public override void Ended() + public override void Ended(GameRuleConfiguration _) { _traitors.Clear(); } diff --git a/Resources/Prototypes/game_rules.yml b/Resources/Prototypes/game_rules.yml index d071913805..145e6d0177 100644 --- a/Resources/Prototypes/game_rules.yml +++ b/Resources/Prototypes/game_rules.yml @@ -1,29 +1,58 @@ - type: gameRule id: DeathMatch + config: + !type:GenericGameRuleConfiguration + id: DeathMatch - type: gameRule id: InactivityTimeRestart + config: + !type:InactivityGameRuleConfiguration + inactivityMaxTime: 600 + roundEndDelay: 10 - type: gameRule id: MaxTimeRestart + config: + !type:MaxTimeRestartRuleConfiguration + roundMaxTime: 300 + roundEndDelay: 10 - type: gameRule id: Nukeops + config: + !type:GenericGameRuleConfiguration + id: Nukeops - type: gameRule id: Pirates - type: gameRule id: Suspicion + config: + !type:GenericGameRuleConfiguration + id: Suspicion - type: gameRule id: Traitor + config: + !type:GenericGameRuleConfiguration + id: Traitor - type: gameRule id: TraitorDeathMatch + config: + !type:GenericGameRuleConfiguration + id: TraitorDeathMatch - type: gameRule id: Sandbox + config: + !type:GenericGameRuleConfiguration + id: Sandbox - type: gameRule id: Secret + config: + !type:GenericGameRuleConfiguration + id: Secret