fix antag selection being evil (#28197)
* fix antag selection being evil * fix test * untroll the other tests * remove role timer troll * Allow tests to modify antag preferences * Fix antag selection * Misc test fixes * Add AntagPreferenceTest * Fix lazy mistakes * Test cleanup * Try stop players in lobbies from being assigned mid-round antags * ranting * I am going insane --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Preferences.Managers;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -128,4 +131,29 @@ public sealed partial class TestPair
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for enabling or disabling a antag role
|
||||
/// </summary>
|
||||
public async Task SetAntagPref(ProtoId<AntagPrototype> id, bool value)
|
||||
{
|
||||
var prefMan = Server.ResolveDependency<IServerPreferencesManager>();
|
||||
|
||||
var prefs = prefMan.GetPreferences(Client.User!.Value);
|
||||
// what even is the point of ICharacterProfile if we always cast it to HumanoidCharacterProfile to make it usable?
|
||||
var profile = (HumanoidCharacterProfile) prefs.SelectedCharacter;
|
||||
|
||||
Assert.That(profile.AntagPreferences.Contains(id), Is.EqualTo(!value));
|
||||
var newProfile = profile.WithAntagPreference(id, value);
|
||||
|
||||
await Server.WaitPost(() =>
|
||||
{
|
||||
prefMan.SetProfile(Client.User.Value, prefs.SelectedCharacterIndex, newProfile).Wait();
|
||||
});
|
||||
|
||||
// And why the fuck does it always create a new preference and profile object instead of just reusing them?
|
||||
var newPrefs = prefMan.GetPreferences(Client.User.Value);
|
||||
var newProf = (HumanoidCharacterProfile) newPrefs.SelectedCharacter;
|
||||
Assert.That(newProf.AntagPreferences.Contains(id), Is.EqualTo(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,11 +65,11 @@ public static partial class PoolManager
|
||||
|
||||
options.BeforeStart += () =>
|
||||
{
|
||||
// Server-only systems (i.e., systems that subscribe to events with server-only components)
|
||||
var entSysMan = IoCManager.Resolve<IEntitySystemManager>();
|
||||
entSysMan.LoadExtraSystemType<ResettingEntitySystemTests.TestRoundRestartCleanupEvent>();
|
||||
entSysMan.LoadExtraSystemType<InteractionSystemTests.TestInteractionSystem>();
|
||||
entSysMan.LoadExtraSystemType<DeviceNetworkTestSystem>();
|
||||
entSysMan.LoadExtraSystemType<TestDestructibleListenerSystem>();
|
||||
|
||||
IoCManager.Resolve<ILogManager>().GetSawmill("loc").Level = LogLevel.Error;
|
||||
IoCManager.Resolve<IConfigurationManager>()
|
||||
.OnValueChanged(RTCVars.FailureLogLevel, value => logHandler.FailureLevel = value, true);
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.Antag.Components;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Shared.GameTicking;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.GameRules;
|
||||
|
||||
// Once upon a time, players in the lobby weren't ever considered eligible for antag roles.
|
||||
// Lets not let that happen again.
|
||||
[TestFixture]
|
||||
public sealed class AntagPreferenceTest
|
||||
{
|
||||
[Test]
|
||||
public async Task TestLobbyPlayersValid()
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient(new PoolSettings
|
||||
{
|
||||
DummyTicker = false,
|
||||
Connected = true,
|
||||
InLobby = true
|
||||
});
|
||||
|
||||
var server = pair.Server;
|
||||
var client = pair.Client;
|
||||
var ticker = server.System<GameTicker>();
|
||||
var sys = server.System<AntagSelectionSystem>();
|
||||
|
||||
// Initially in the lobby
|
||||
Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby));
|
||||
Assert.That(client.AttachedEntity, Is.Null);
|
||||
Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.NotReadyToPlay));
|
||||
|
||||
EntityUid uid = default;
|
||||
await server.WaitPost(() => uid = server.EntMan.Spawn("Traitor"));
|
||||
var rule = new Entity<AntagSelectionComponent>(uid, server.EntMan.GetComponent<AntagSelectionComponent>(uid));
|
||||
var def = rule.Comp.Definitions.Single();
|
||||
|
||||
// IsSessionValid & IsEntityValid are preference agnostic and should always be true for players in the lobby.
|
||||
// Though maybe that will change in the future, but then GetPlayerPool() needs to be updated to reflect that.
|
||||
Assert.That(sys.IsSessionValid(rule, pair.Player, def), Is.True);
|
||||
Assert.That(sys.IsEntityValid(client.AttachedEntity, def), Is.True);
|
||||
|
||||
// By default, traitor/antag preferences are disabled, so the pool should be empty.
|
||||
var sessions = new List<ICommonSession>{pair.Player!};
|
||||
var pool = sys.GetPlayerPool(rule, sessions, def);
|
||||
Assert.That(pool.Count, Is.EqualTo(0));
|
||||
|
||||
// Opt into the traitor role.
|
||||
await pair.SetAntagPref("Traitor", true);
|
||||
|
||||
Assert.That(sys.IsSessionValid(rule, pair.Player, def), Is.True);
|
||||
Assert.That(sys.IsEntityValid(client.AttachedEntity, def), Is.True);
|
||||
pool = sys.GetPlayerPool(rule, sessions, def);
|
||||
Assert.That(pool.Count, Is.EqualTo(1));
|
||||
pool.TryPickAndTake(pair.Server.ResolveDependency<IRobustRandom>(), out var picked);
|
||||
Assert.That(picked, Is.EqualTo(pair.Player));
|
||||
Assert.That(sessions.Count, Is.EqualTo(1));
|
||||
|
||||
// opt back out
|
||||
await pair.SetAntagPref("Traitor", false);
|
||||
|
||||
Assert.That(sys.IsSessionValid(rule, pair.Player, def), Is.True);
|
||||
Assert.That(sys.IsEntityValid(client.AttachedEntity, def), Is.True);
|
||||
pool = sys.GetPlayerPool(rule, sessions, def);
|
||||
Assert.That(pool.Count, Is.EqualTo(0));
|
||||
|
||||
await server.WaitPost(() => server.EntMan.DeleteEntity(uid));
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,9 @@ public sealed class NukeOpsTest
|
||||
Assert.That(client.AttachedEntity, Is.Null);
|
||||
Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.NotReadyToPlay));
|
||||
|
||||
// Opt into the nukies role.
|
||||
await pair.SetAntagPref("NukeopsCommander", true);
|
||||
|
||||
// There are no grids or maps
|
||||
Assert.That(entMan.Count<MapComponent>(), Is.Zero);
|
||||
Assert.That(entMan.Count<MapGridComponent>(), Is.Zero);
|
||||
@@ -198,6 +201,7 @@ public sealed class NukeOpsTest
|
||||
|
||||
ticker.SetGamePreset((GamePresetPrototype?)null);
|
||||
server.CfgMan.SetCVar(CCVars.GridFill, false);
|
||||
await pair.SetAntagPref("NukeopsCommander", false);
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,7 +407,6 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
[Reflect(false)]
|
||||
public sealed class TestInteractionSystem : EntitySystem
|
||||
{
|
||||
public EntityEventHandler<InteractUsingEvent>? InteractUsingEvent;
|
||||
|
||||
@@ -9,7 +9,6 @@ namespace Content.IntegrationTests.Tests
|
||||
[TestOf(typeof(RoundRestartCleanupEvent))]
|
||||
public sealed class ResettingEntitySystemTests
|
||||
{
|
||||
[Reflect(false)]
|
||||
public sealed class TestRoundRestartCleanupEvent : EntitySystem
|
||||
{
|
||||
public bool HasBeenReset { get; set; }
|
||||
@@ -49,8 +48,6 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
system.HasBeenReset = false;
|
||||
|
||||
Assert.That(system.HasBeenReset, Is.False);
|
||||
|
||||
gameTicker.RestartRound();
|
||||
|
||||
Assert.That(system.HasBeenReset);
|
||||
|
||||
Reference in New Issue
Block a user