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