Merge remote-tracking branch 'upstream/master' into fucking-upstream
This commit is contained in:
@@ -32,8 +32,8 @@ public sealed class AddTests
|
||||
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
var testMap = await pair.CreateTestMap();
|
||||
var coordinates = testMap.GridCoords;
|
||||
await pair.CreateTestMap();
|
||||
var coordinates = pair.TestMap.GridCoords;
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var entity = sEntities.SpawnEntity(null, coordinates);
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.GameTicking.Commands;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Commands
|
||||
@@ -40,8 +41,7 @@ namespace Content.IntegrationTests.Tests.Commands
|
||||
|
||||
tickBeforeRestart = entityManager.CurrentTick;
|
||||
|
||||
var command = new RestartRoundNowCommand();
|
||||
command.Execute(null, string.Empty, Array.Empty<string>());
|
||||
gameTicker.RestartRound();
|
||||
|
||||
if (lobbyEnabled)
|
||||
{
|
||||
|
||||
@@ -19,36 +19,45 @@ namespace Content.IntegrationTests.Tests.Damageable
|
||||
# Define some damage groups
|
||||
- type: damageType
|
||||
id: TestDamage1
|
||||
name: damage-type-blunt
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage2a
|
||||
name: damage-type-blunt
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage2b
|
||||
name: damage-type-blunt
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage3a
|
||||
name: damage-type-blunt
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage3b
|
||||
name: damage-type-blunt
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage3c
|
||||
name: damage-type-blunt
|
||||
|
||||
# Define damage Groups with 1,2,3 damage types
|
||||
- type: damageGroup
|
||||
id: TestGroup1
|
||||
name: damage-group-brute
|
||||
damageTypes:
|
||||
- TestDamage1
|
||||
|
||||
- type: damageGroup
|
||||
id: TestGroup2
|
||||
name: damage-group-brute
|
||||
damageTypes:
|
||||
- TestDamage2a
|
||||
- TestDamage2b
|
||||
|
||||
- type: damageGroup
|
||||
id: TestGroup3
|
||||
name: damage-group-brute
|
||||
damageTypes:
|
||||
- TestDamage3a
|
||||
- TestDamage3b
|
||||
|
||||
@@ -12,24 +12,31 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
public const string DamagePrototypes = $@"
|
||||
- type: damageType
|
||||
id: TestBlunt
|
||||
name: damage-type-blunt
|
||||
|
||||
- type: damageType
|
||||
id: TestSlash
|
||||
name: damage-type-slash
|
||||
|
||||
- type: damageType
|
||||
id: TestPiercing
|
||||
name: damage-type-piercing
|
||||
|
||||
- type: damageType
|
||||
id: TestHeat
|
||||
name: damage-type-heat
|
||||
|
||||
- type: damageType
|
||||
id: TestShock
|
||||
name: damage-type-shock
|
||||
|
||||
- type: damageType
|
||||
id: TestCold
|
||||
name: damage-type-cold
|
||||
|
||||
- type: damageGroup
|
||||
id: TestBrute
|
||||
name: damage-group-brute
|
||||
damageTypes:
|
||||
- TestBlunt
|
||||
- TestSlash
|
||||
@@ -37,6 +44,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
|
||||
- type: damageGroup
|
||||
id: TestBurn
|
||||
name: damage-group-burn
|
||||
damageTypes:
|
||||
- TestHeat
|
||||
- TestShock
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork
|
||||
DeviceNetworkComponent networkComponent1 = null;
|
||||
DeviceNetworkComponent networkComponent2 = null;
|
||||
WiredNetworkComponent wiredNetworkComponent = null;
|
||||
var grid = testMap.MapGrid;
|
||||
var grid = testMap.Grid.Comp;
|
||||
|
||||
var testValue = "test";
|
||||
var payload = new NetworkPayload
|
||||
|
||||
@@ -3,8 +3,6 @@ using Content.IntegrationTests.Tests.Construction.Interaction;
|
||||
using Content.IntegrationTests.Tests.Interaction;
|
||||
using Content.IntegrationTests.Tests.Weldable;
|
||||
using Content.Shared.Tools.Components;
|
||||
using Content.Server.Tools.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.DoAfter;
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace Content.IntegrationTests.Tests.Doors
|
||||
// Sloth: Okay I'm sorry but I hate having to rewrite tests for every refactor
|
||||
// If you see this yell at me in discord so I can continue to pretend this didn't happen.
|
||||
// REMINDER THAT I STILL HAVE TO FIX THIS TEST EVERY OTHER PHYSICS PR
|
||||
// Assert.That(AirlockPhysicsDummy.Transform.MapPosition.X, Is.GreaterThan(AirlockPhysicsDummyStartingX));
|
||||
// _transform.GetMapCoordinates(UID HERE, xform: Assert.That(AirlockPhysicsDummy.Transform).X, Is.GreaterThan(AirlockPhysicsDummyStartingX));
|
||||
|
||||
// Blocked by the airlock
|
||||
await server.WaitAssertion(() =>
|
||||
|
||||
@@ -354,41 +354,18 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
await using var pair = await PoolManager.GetServerClient();
|
||||
var server = pair.Server;
|
||||
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var componentFactory = server.ResolveDependency<IComponentFactory>();
|
||||
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
|
||||
var mapSystem = entityManager.System<SharedMapSystem>();
|
||||
var logmill = server.ResolveDependency<ILogManager>().GetSawmill("EntityTest");
|
||||
|
||||
Entity<MapGridComponent> grid = default!;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
// Create a one tile grid to stave off the grid 0 monsters
|
||||
var mapId = mapManager.CreateMap();
|
||||
|
||||
mapManager.AddUninitializedMap(mapId);
|
||||
|
||||
grid = mapManager.CreateGridEntity(mapId);
|
||||
|
||||
var tileDefinition = tileDefinitionManager["Plating"];
|
||||
var tile = new Tile(tileDefinition.TileId);
|
||||
var coordinates = new EntityCoordinates(grid.Owner, Vector2.Zero);
|
||||
|
||||
mapSystem.SetTile(grid.Owner, grid.Comp!, coordinates, tile);
|
||||
|
||||
mapManager.DoMapInitialize(mapId);
|
||||
});
|
||||
|
||||
await pair.CreateTestMap();
|
||||
await server.WaitRunTicks(5);
|
||||
var testLocation = pair.TestMap.GridCoords;
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
var testLocation = new EntityCoordinates(grid.Owner, Vector2.Zero);
|
||||
|
||||
foreach (var type in componentFactory.AllRegisteredTypes)
|
||||
{
|
||||
|
||||
@@ -46,17 +46,14 @@ namespace Content.IntegrationTests.Tests.Fluids
|
||||
var server = pair.Server;
|
||||
|
||||
var testMap = await pair.CreateTestMap();
|
||||
var grid = testMap.Grid.Comp;
|
||||
|
||||
var entitySystemManager = server.ResolveDependency<IEntitySystemManager>();
|
||||
var spillSystem = entitySystemManager.GetEntitySystem<PuddleSystem>();
|
||||
|
||||
MapGridComponent grid = null;
|
||||
|
||||
// Remove all tiles
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
grid = testMap.MapGrid;
|
||||
|
||||
foreach (var tile in grid.GetAllTiles())
|
||||
{
|
||||
grid.SetTile(tile.GridIndices, Tile.Empty);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
#nullable enable
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Components;
|
||||
using Content.Server.GameTicking.Presets;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.GameTicking;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.GameRules;
|
||||
|
||||
[TestFixture]
|
||||
public sealed class FailAndStartPresetTest
|
||||
{
|
||||
[TestPrototypes]
|
||||
private const string Prototypes = @"
|
||||
- type: gamePreset
|
||||
id: TestPreset
|
||||
alias:
|
||||
- nukeops
|
||||
name: Test Preset
|
||||
description: """"
|
||||
showInVote: false
|
||||
rules:
|
||||
- TestRule
|
||||
|
||||
- type: gamePreset
|
||||
id: TestPresetTenPlayers
|
||||
alias:
|
||||
- nukeops
|
||||
name: Test Preset 10 players
|
||||
description: """"
|
||||
showInVote: false
|
||||
rules:
|
||||
- TestRuleTenPlayers
|
||||
|
||||
- type: entity
|
||||
id: TestRule
|
||||
parent: BaseGameRule
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: GameRule
|
||||
minPlayers: 0
|
||||
- type: TestRule
|
||||
|
||||
- type: entity
|
||||
id: TestRuleTenPlayers
|
||||
parent: BaseGameRule
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: GameRule
|
||||
minPlayers: 10
|
||||
- type: TestRule
|
||||
";
|
||||
|
||||
/// <summary>
|
||||
/// Test that a nuke ops gamemode can start after failing to start once.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task FailAndStartTest()
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient(new PoolSettings
|
||||
{
|
||||
Dirty = true,
|
||||
DummyTicker = false,
|
||||
Connected = true,
|
||||
InLobby = true
|
||||
});
|
||||
|
||||
var server = pair.Server;
|
||||
var client = pair.Client;
|
||||
var entMan = server.EntMan;
|
||||
var ticker = server.System<GameTicker>();
|
||||
server.System<TestRuleSystem>().Run = true;
|
||||
|
||||
Assert.That(server.CfgMan.GetCVar(CCVars.GridFill), Is.False);
|
||||
Assert.That(server.CfgMan.GetCVar(CCVars.GameLobbyFallbackEnabled), Is.True);
|
||||
Assert.That(server.CfgMan.GetCVar(CCVars.GameLobbyDefaultPreset), Is.EqualTo("secret"));
|
||||
server.CfgMan.SetCVar(CCVars.GridFill, true);
|
||||
server.CfgMan.SetCVar(CCVars.GameLobbyFallbackEnabled, false);
|
||||
server.CfgMan.SetCVar(CCVars.GameLobbyDefaultPreset, "TestPreset");
|
||||
|
||||
// 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));
|
||||
|
||||
// Try to start nukeops without readying up
|
||||
await pair.WaitCommand("setgamepreset TestPresetTenPlayers");
|
||||
await pair.WaitCommand("startround");
|
||||
await pair.RunTicksSync(10);
|
||||
|
||||
// Game should not have started
|
||||
Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby));
|
||||
Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.NotReadyToPlay));
|
||||
Assert.That(!client.EntMan.EntityExists(client.AttachedEntity));
|
||||
var player = pair.Player!.AttachedEntity;
|
||||
Assert.That(!entMan.EntityExists(player));
|
||||
|
||||
// Ready up and start nukeops
|
||||
await pair.WaitClientCommand("toggleready True");
|
||||
Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.ReadyToPlay));
|
||||
await pair.WaitCommand("setgamepreset TestPreset");
|
||||
await pair.WaitCommand("startround");
|
||||
await pair.RunTicksSync(10);
|
||||
|
||||
// Game should have started
|
||||
Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
|
||||
Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.JoinedGame));
|
||||
Assert.That(client.EntMan.EntityExists(client.AttachedEntity));
|
||||
player = pair.Player!.AttachedEntity!.Value;
|
||||
Assert.That(entMan.EntityExists(player));
|
||||
|
||||
ticker.SetGamePreset((GamePresetPrototype?)null);
|
||||
server.CfgMan.SetCVar(CCVars.GridFill, false);
|
||||
server.CfgMan.SetCVar(CCVars.GameLobbyFallbackEnabled, true);
|
||||
server.CfgMan.SetCVar(CCVars.GameLobbyDefaultPreset, "secret");
|
||||
server.System<TestRuleSystem>().Run = false;
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TestRuleSystem : EntitySystem
|
||||
{
|
||||
public bool Run;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<RoundStartAttemptEvent>(OnRoundStartAttempt);
|
||||
}
|
||||
|
||||
private void OnRoundStartAttempt(RoundStartAttemptEvent args)
|
||||
{
|
||||
if (!Run)
|
||||
return;
|
||||
|
||||
if (args.Forced || args.Cancelled)
|
||||
return;
|
||||
|
||||
var query = EntityQueryEnumerator<TestRuleComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out _, out _, out var gameRule))
|
||||
{
|
||||
var minPlayers = gameRule.MinPlayers;
|
||||
if (args.Players.Length >= minPlayers)
|
||||
continue;
|
||||
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class TestRuleComponent : Component;
|
||||
207
Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs
Normal file
207
Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
#nullable enable
|
||||
using System.Linq;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Presets;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Pinpointer;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.NPC.Systems;
|
||||
using Content.Shared.NukeOps;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map.Components;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.GameRules;
|
||||
|
||||
[TestFixture]
|
||||
public sealed class NukeOpsTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Check that a nuke ops game mode can start without issue. I.e., that the nuke station and such all get loaded.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task TryStopNukeOpsFromConstantlyFailing()
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient(new PoolSettings
|
||||
{
|
||||
Dirty = true,
|
||||
DummyTicker = false,
|
||||
Connected = true,
|
||||
InLobby = true
|
||||
});
|
||||
|
||||
var server = pair.Server;
|
||||
var client = pair.Client;
|
||||
var entMan = server.EntMan;
|
||||
var mapSys = server.System<MapSystem>();
|
||||
var ticker = server.System<GameTicker>();
|
||||
var mindSys = server.System<MindSystem>();
|
||||
var roleSys = server.System<RoleSystem>();
|
||||
var invSys = server.System<InventorySystem>();
|
||||
var factionSys = server.System<NpcFactionSystem>();
|
||||
|
||||
Assert.That(server.CfgMan.GetCVar(CCVars.GridFill), Is.False);
|
||||
server.CfgMan.SetCVar(CCVars.GridFill, true);
|
||||
|
||||
// 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));
|
||||
|
||||
// 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);
|
||||
Assert.That(entMan.Count<StationMapComponent>(), Is.Zero);
|
||||
Assert.That(entMan.Count<StationMemberComponent>(), Is.Zero);
|
||||
Assert.That(entMan.Count<StationCentcommComponent>(), Is.Zero);
|
||||
|
||||
// And no nukie related components
|
||||
Assert.That(entMan.Count<NukeopsRuleComponent>(), Is.Zero);
|
||||
Assert.That(entMan.Count<NukeopsRoleComponent>(), Is.Zero);
|
||||
Assert.That(entMan.Count<NukeOperativeComponent>(), Is.Zero);
|
||||
Assert.That(entMan.Count<NukeOpsShuttleComponent>(), Is.Zero);
|
||||
Assert.That(entMan.Count<NukeOperativeSpawnerComponent>(), Is.Zero);
|
||||
|
||||
// Ready up and start nukeops
|
||||
await pair.WaitClientCommand("toggleready True");
|
||||
Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.ReadyToPlay));
|
||||
await pair.WaitCommand("forcepreset Nukeops");
|
||||
await pair.RunTicksSync(10);
|
||||
|
||||
// Game should have started
|
||||
Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
|
||||
Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.JoinedGame));
|
||||
Assert.That(client.EntMan.EntityExists(client.AttachedEntity));
|
||||
var player = pair.Player!.AttachedEntity!.Value;
|
||||
Assert.That(entMan.EntityExists(player));
|
||||
|
||||
// Maps now exist
|
||||
Assert.That(entMan.Count<MapComponent>(), Is.GreaterThan(0));
|
||||
Assert.That(entMan.Count<MapGridComponent>(), Is.GreaterThan(0));
|
||||
Assert.That(entMan.Count<StationDataComponent>(), Is.EqualTo(2)); // The main station & nukie station
|
||||
Assert.That(entMan.Count<StationMemberComponent>(), Is.GreaterThan(3)); // Each station has at least 1 grid, plus some shuttles
|
||||
Assert.That(entMan.Count<StationCentcommComponent>(), Is.EqualTo(1));
|
||||
|
||||
// And we now have nukie related components
|
||||
Assert.That(entMan.Count<NukeopsRuleComponent>(), Is.EqualTo(1));
|
||||
Assert.That(entMan.Count<NukeopsRoleComponent>(), Is.EqualTo(1));
|
||||
Assert.That(entMan.Count<NukeOperativeComponent>(), Is.EqualTo(1));
|
||||
Assert.That(entMan.Count<NukeOpsShuttleComponent>(), Is.EqualTo(1));
|
||||
|
||||
// The player entity should be the nukie commander
|
||||
var mind = mindSys.GetMind(player)!.Value;
|
||||
Assert.That(entMan.HasComponent<NukeOperativeComponent>(player));
|
||||
Assert.That(roleSys.MindIsAntagonist(mind));
|
||||
Assert.That(roleSys.MindHasRole<NukeopsRoleComponent>(mind));
|
||||
Assert.That(factionSys.IsMember(player, "Syndicate"), Is.True);
|
||||
Assert.That(factionSys.IsMember(player, "NanoTrasen"), Is.False);
|
||||
|
||||
var roles = roleSys.MindGetAllRoles(mind);
|
||||
var cmdRoles = roles.Where(x => x.Prototype == "NukeopsCommander" && x.Component is NukeopsRoleComponent);
|
||||
Assert.That(cmdRoles.Count(), Is.EqualTo(1));
|
||||
|
||||
// The game rule exists, and all the stations/shuttles/maps are properly initialized
|
||||
var rule = entMan.AllComponents<NukeopsRuleComponent>().Single().Component;
|
||||
var mapRule = entMan.AllComponents<LoadMapRuleComponent>().Single().Component;
|
||||
foreach (var grid in mapRule.MapGrids)
|
||||
{
|
||||
Assert.That(entMan.EntityExists(grid));
|
||||
Assert.That(entMan.HasComponent<MapGridComponent>(grid));
|
||||
Assert.That(entMan.HasComponent<StationMemberComponent>(grid));
|
||||
}
|
||||
Assert.That(entMan.EntityExists(rule.TargetStation));
|
||||
|
||||
Assert.That(entMan.HasComponent<StationDataComponent>(rule.TargetStation));
|
||||
|
||||
var nukieShuttlEnt = entMan.AllComponents<NukeOpsShuttleComponent>().FirstOrDefault().Uid;
|
||||
Assert.That(entMan.EntityExists(nukieShuttlEnt));
|
||||
|
||||
EntityUid? nukieStationEnt = null;
|
||||
foreach (var grid in mapRule.MapGrids)
|
||||
{
|
||||
if (entMan.HasComponent<StationMemberComponent>(grid))
|
||||
{
|
||||
nukieStationEnt = grid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.That(entMan.EntityExists(nukieStationEnt));
|
||||
var nukieStation = entMan.GetComponent<StationMemberComponent>(nukieStationEnt!.Value);
|
||||
|
||||
Assert.That(entMan.EntityExists(nukieStation.Station));
|
||||
Assert.That(nukieStation.Station, Is.Not.EqualTo(rule.TargetStation));
|
||||
|
||||
Assert.That(server.MapMan.MapExists(mapRule.Map));
|
||||
var nukieMap = mapSys.GetMap(mapRule.Map!.Value);
|
||||
|
||||
var targetStation = entMan.GetComponent<StationDataComponent>(rule.TargetStation!.Value);
|
||||
var targetGrid = targetStation.Grids.First();
|
||||
var targetMap = entMan.GetComponent<TransformComponent>(targetGrid).MapUid!.Value;
|
||||
Assert.That(targetMap, Is.Not.EqualTo(nukieMap));
|
||||
|
||||
Assert.That(entMan.GetComponent<TransformComponent>(player).MapUid, Is.EqualTo(nukieMap));
|
||||
Assert.That(entMan.GetComponent<TransformComponent>(nukieStationEnt.Value).MapUid, Is.EqualTo(nukieMap));
|
||||
Assert.That(entMan.GetComponent<TransformComponent>(nukieShuttlEnt).MapUid, Is.EqualTo(nukieMap));
|
||||
|
||||
// The maps are all map-initialized, including the player
|
||||
// Yes, this is necessary as this has repeatedly been broken somehow.
|
||||
Assert.That(mapSys.IsInitialized(nukieMap));
|
||||
Assert.That(mapSys.IsInitialized(targetMap));
|
||||
Assert.That(mapSys.IsPaused(nukieMap), Is.False);
|
||||
Assert.That(mapSys.IsPaused(targetMap), Is.False);
|
||||
|
||||
EntityLifeStage LifeStage(EntityUid? uid) => entMan.GetComponent<MetaDataComponent>(uid!.Value).EntityLifeStage;
|
||||
Assert.That(LifeStage(player), Is.GreaterThan(EntityLifeStage.Initialized));
|
||||
Assert.That(LifeStage(nukieMap), Is.GreaterThan(EntityLifeStage.Initialized));
|
||||
Assert.That(LifeStage(targetMap), Is.GreaterThan(EntityLifeStage.Initialized));
|
||||
Assert.That(LifeStage(nukieStationEnt.Value), Is.GreaterThan(EntityLifeStage.Initialized));
|
||||
Assert.That(LifeStage(nukieShuttlEnt), Is.GreaterThan(EntityLifeStage.Initialized));
|
||||
Assert.That(LifeStage(rule.TargetStation), Is.GreaterThan(EntityLifeStage.Initialized));
|
||||
|
||||
// Make sure the player has hands. We've had fucking disarmed nukies before.
|
||||
Assert.That(entMan.HasComponent<HandsComponent>(player));
|
||||
Assert.That(entMan.GetComponent<HandsComponent>(player).Hands.Count, Is.GreaterThan(0));
|
||||
|
||||
// While we're at it, lets make sure they aren't naked. I don't know how many inventory slots all mobs will be
|
||||
// likely to have in the future. But nukies should probably have at least 3 slots with something in them.
|
||||
var enumerator = invSys.GetSlotEnumerator(player);
|
||||
int total = 0;
|
||||
while (enumerator.NextItem(out _))
|
||||
{
|
||||
total++;
|
||||
}
|
||||
Assert.That(total, Is.GreaterThan(3));
|
||||
|
||||
// Finally lets check the nukie commander passed basic training and figured out how to breathe.
|
||||
var totalSeconds = 30;
|
||||
var totalTicks = (int) Math.Ceiling(totalSeconds / server.Timing.TickPeriod.TotalSeconds);
|
||||
int increment = 5;
|
||||
var resp = entMan.GetComponent<RespiratorComponent>(player);
|
||||
var damage = entMan.GetComponent<DamageableComponent>(player);
|
||||
for (var tick = 0; tick < totalTicks; tick += increment)
|
||||
{
|
||||
await pair.RunTicksSync(increment);
|
||||
Assert.That(resp.SuffocationCycles, Is.LessThanOrEqualTo(resp.SuffocationCycleThreshold));
|
||||
Assert.That(damage.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
}
|
||||
|
||||
ticker.SetGamePreset((GamePresetPrototype?)null);
|
||||
server.CfgMan.SetCVar(CCVars.GridFill, false);
|
||||
await pair.SetAntagPref("NukeopsCommander", false);
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Commands;
|
||||
using Content.Server.GameTicking.Components;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Shared.CCVar;
|
||||
@@ -19,6 +20,9 @@ namespace Content.IntegrationTests.Tests.GameRules
|
||||
await using var pair = await PoolManager.GetServerClient(new PoolSettings { InLobby = true });
|
||||
var server = pair.Server;
|
||||
|
||||
Assert.That(server.EntMan.Count<GameRuleComponent>(), Is.Zero);
|
||||
Assert.That(server.EntMan.Count<ActiveGameRuleComponent>(), Is.Zero);
|
||||
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var sGameTicker = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<GameTicker>();
|
||||
var sGameTiming = server.ResolveDependency<IGameTiming>();
|
||||
@@ -26,6 +30,9 @@ namespace Content.IntegrationTests.Tests.GameRules
|
||||
sGameTicker.StartGameRule("MaxTimeRestart", out var ruleEntity);
|
||||
Assert.That(entityManager.TryGetComponent<MaxTimeRestartRuleComponent>(ruleEntity, out var maxTime));
|
||||
|
||||
Assert.That(server.EntMan.Count<GameRuleComponent>(), Is.EqualTo(1));
|
||||
Assert.That(server.EntMan.Count<ActiveGameRuleComponent>(), Is.EqualTo(1));
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
Assert.That(sGameTicker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby));
|
||||
@@ -33,6 +40,9 @@ namespace Content.IntegrationTests.Tests.GameRules
|
||||
sGameTicker.StartRound();
|
||||
});
|
||||
|
||||
Assert.That(server.EntMan.Count<GameRuleComponent>(), Is.EqualTo(1));
|
||||
Assert.That(server.EntMan.Count<ActiveGameRuleComponent>(), Is.EqualTo(1));
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
Assert.That(sGameTicker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
|
||||
|
||||
@@ -17,6 +17,7 @@ public sealed class SecretStartsTest
|
||||
|
||||
var server = pair.Server;
|
||||
await server.WaitIdleAsync();
|
||||
var entMan = server.ResolveDependency<IEntityManager>();
|
||||
var gameTicker = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<GameTicker>();
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
@@ -32,10 +33,7 @@ public sealed class SecretStartsTest
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
foreach (var rule in gameTicker.GetAddedGameRules())
|
||||
{
|
||||
Assert.That(gameTicker.GetActiveGameRules(), Does.Contain(rule));
|
||||
}
|
||||
Assert.That(gameTicker.GetAddedGameRules().Count(), Is.GreaterThan(1), $"No additional rules started by secret rule.");
|
||||
|
||||
// End all rules
|
||||
gameTicker.ClearGameRules();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
@@ -24,6 +25,7 @@ public sealed class HandTests
|
||||
var playerMan = server.ResolveDependency<IPlayerManager>();
|
||||
var mapMan = server.ResolveDependency<IMapManager>();
|
||||
var sys = entMan.System<SharedHandsSystem>();
|
||||
var tSys = entMan.System<TransformSystem>();
|
||||
|
||||
var data = await pair.CreateTestMap();
|
||||
await pair.RunTicksSync(5);
|
||||
@@ -35,7 +37,7 @@ public sealed class HandTests
|
||||
{
|
||||
player = playerMan.Sessions.First().AttachedEntity!.Value;
|
||||
var xform = entMan.GetComponent<TransformComponent>(player);
|
||||
item = entMan.SpawnEntity("Crowbar", xform.MapPosition);
|
||||
item = entMan.SpawnEntity("Crowbar", tSys.GetMapCoordinates(player, xform: xform));
|
||||
hands = entMan.GetComponent<HandsComponent>(player);
|
||||
sys.TryPickup(player, item, hands.ActiveHand!);
|
||||
});
|
||||
|
||||
@@ -407,7 +407,6 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
[Reflect(false)]
|
||||
public sealed class TestInteractionSystem : EntitySystem
|
||||
{
|
||||
public EntityEventHandler<InteractUsingEvent>? InteractUsingEvent;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
@@ -32,6 +33,7 @@ namespace Content.IntegrationTests.Tests.Interaction
|
||||
var sEntities = server.ResolveDependency<IEntityManager>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var conSystem = sEntities.EntitySysManager.GetEntitySystem<SharedContainerSystem>();
|
||||
var tSystem = sEntities.EntitySysManager.GetEntitySystem<TransformSystem>();
|
||||
|
||||
EntityUid origin = default;
|
||||
EntityUid other = default;
|
||||
@@ -45,7 +47,7 @@ namespace Content.IntegrationTests.Tests.Interaction
|
||||
origin = sEntities.SpawnEntity(HumanId, coordinates);
|
||||
other = sEntities.SpawnEntity(HumanId, coordinates);
|
||||
conSystem.EnsureContainer<Container>(other, "InRangeUnobstructedTestOtherContainer");
|
||||
mapCoordinates = sEntities.GetComponent<TransformComponent>(other).MapPosition;
|
||||
mapCoordinates = tSystem.GetMapCoordinates(other);
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Shared.Stacks;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using static Robust.UnitTesting.RobustIntegrationTest;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Interaction;
|
||||
|
||||
@@ -54,7 +55,7 @@ public abstract partial class InteractionTest
|
||||
/// <summary>
|
||||
/// Convert applicable entity prototypes into stack prototypes.
|
||||
/// </summary>
|
||||
public void ConvertToStack(IPrototypeManager protoMan, IComponentFactory factory)
|
||||
public async Task ConvertToStack(IPrototypeManager protoMan, IComponentFactory factory, ServerIntegrationInstance server)
|
||||
{
|
||||
if (Converted)
|
||||
return;
|
||||
@@ -73,11 +74,14 @@ public abstract partial class InteractionTest
|
||||
return;
|
||||
}
|
||||
|
||||
if (entProto.TryGetComponent<StackComponent>(factory.GetComponentName(typeof(StackComponent)),
|
||||
out var stackComp))
|
||||
StackComponent? stack = null;
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
Prototype = stackComp.StackTypeId;
|
||||
}
|
||||
entProto.TryGetComponent(factory.GetComponentName(typeof(StackComponent)), out stack);
|
||||
});
|
||||
|
||||
if (stack != null)
|
||||
Prototype = stack.StackTypeId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +104,14 @@ public abstract partial class InteractionTest
|
||||
return default;
|
||||
}
|
||||
|
||||
if (entProto.TryGetComponent<StackComponent>(Factory.GetComponentName(typeof(StackComponent)),
|
||||
out var stackComp))
|
||||
StackComponent? stack = null;
|
||||
await Server.WaitPost(() =>
|
||||
{
|
||||
return await SpawnEntity((stackComp.StackTypeId, spec.Quantity), coords);
|
||||
}
|
||||
entProto.TryGetComponent(Factory.GetComponentName(typeof(StackComponent)), out stack);
|
||||
});
|
||||
|
||||
if (stack != null)
|
||||
return await SpawnEntity((stack.StackTypeId, spec.Quantity), coords);
|
||||
|
||||
Assert.That(spec.Quantity, Is.EqualTo(1), "SpawnEntity only supports returning a singular entity");
|
||||
await Server.WaitPost(() => uid = SEntMan.SpawnEntity(spec.Prototype, coords));
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Shared.Stacks;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.UnitTesting.RobustIntegrationTest;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Interaction;
|
||||
|
||||
@@ -111,7 +112,7 @@ public abstract partial class InteractionTest
|
||||
/// <summary>
|
||||
/// Convert applicable entity prototypes into stack prototypes.
|
||||
/// </summary>
|
||||
public void ConvertToStacks(IPrototypeManager protoMan, IComponentFactory factory)
|
||||
public async Task ConvertToStacks(IPrototypeManager protoMan, IComponentFactory factory, ServerIntegrationInstance server)
|
||||
{
|
||||
if (Converted)
|
||||
return;
|
||||
@@ -130,14 +131,17 @@ public abstract partial class InteractionTest
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!entProto.TryGetComponent<StackComponent>(factory.GetComponentName(typeof(StackComponent)),
|
||||
out var stackComp))
|
||||
StackComponent? stack = null;
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
entProto.TryGetComponent(factory.GetComponentName(typeof(StackComponent)), out stack);
|
||||
});
|
||||
|
||||
if (stack == null)
|
||||
continue;
|
||||
}
|
||||
|
||||
toRemove.Add(id);
|
||||
toAdd.Add((stackComp.StackTypeId, quantity));
|
||||
toAdd.Add((stack.StackTypeId, quantity));
|
||||
}
|
||||
|
||||
foreach (var id in toRemove)
|
||||
|
||||
@@ -5,12 +5,9 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using Content.Client.Construction;
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Construction.Components;
|
||||
using Content.Server.Gravity;
|
||||
using Content.Server.Item;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
@@ -634,7 +631,7 @@ public abstract partial class InteractionTest
|
||||
var entities = await DoEntityLookup(flags);
|
||||
var found = ToEntityCollection(entities);
|
||||
expected.Remove(found);
|
||||
expected.ConvertToStacks(ProtoMan, Factory);
|
||||
await expected.ConvertToStacks(ProtoMan, Factory, Server);
|
||||
|
||||
if (expected.Entities.Count == 0)
|
||||
return;
|
||||
@@ -670,7 +667,7 @@ public abstract partial class InteractionTest
|
||||
LookupFlags flags = LookupFlags.Uncontained | LookupFlags.Contained,
|
||||
bool shouldSucceed = true)
|
||||
{
|
||||
spec.ConvertToStack(ProtoMan, Factory);
|
||||
await spec.ConvertToStack(ProtoMan, Factory, Server);
|
||||
|
||||
var entities = await DoEntityLookup(flags);
|
||||
foreach (var uid in entities)
|
||||
@@ -767,14 +764,9 @@ public abstract partial class InteractionTest
|
||||
await Pair.RunTicksSync(ticks);
|
||||
}
|
||||
|
||||
protected int SecondsToTicks(float seconds)
|
||||
{
|
||||
return (int) Math.Ceiling(seconds / TickPeriod);
|
||||
}
|
||||
|
||||
protected async Task RunSeconds(float seconds)
|
||||
{
|
||||
await RunTicks(SecondsToTicks(seconds));
|
||||
await Pair.RunSeconds(seconds);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -825,7 +817,7 @@ public abstract partial class InteractionTest
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ui.OpenInterfaces.TryGetValue(key, out bui))
|
||||
if (!ui.ClientOpenInterfaces.TryGetValue(key, out bui))
|
||||
{
|
||||
if (shouldSucceed)
|
||||
Assert.Fail($"Entity {SEntMan.ToPrettyString(SEntMan.GetEntity(target.Value))} does not have an open bui with key {key.GetType()}.{key}.");
|
||||
@@ -989,7 +981,7 @@ public abstract partial class InteractionTest
|
||||
/// </summary>
|
||||
protected async Task AddGravity(EntityUid? uid = null)
|
||||
{
|
||||
var target = uid ?? MapData.GridUid;
|
||||
var target = uid ?? MapData.Grid;
|
||||
await Server.WaitPost(() =>
|
||||
{
|
||||
var gravity = SEntMan.EnsureComponent<GravityComponent>(target);
|
||||
|
||||
@@ -12,7 +12,6 @@ using Content.Shared.Body.Part;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Server.Item;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Players;
|
||||
using Robust.Client.Input;
|
||||
@@ -184,7 +183,7 @@ public abstract partial class InteractionTest
|
||||
await Pair.CreateTestMap();
|
||||
PlayerCoords = SEntMan.GetNetCoordinates(MapData.GridCoords.Offset(new Vector2(0.5f, 0.5f)).WithEntityId(MapData.MapUid, Transform, SEntMan));
|
||||
TargetCoords = SEntMan.GetNetCoordinates(MapData.GridCoords.Offset(new Vector2(1.5f, 0.5f)).WithEntityId(MapData.MapUid, Transform, SEntMan));
|
||||
await SetTile(Plating, grid: MapData.MapGrid);
|
||||
await SetTile(Plating, grid: MapData.Grid.Comp);
|
||||
|
||||
// Get player data
|
||||
var sPlayerMan = Server.ResolveDependency<Robust.Server.Player.IPlayerManager>();
|
||||
|
||||
@@ -31,7 +31,7 @@ public abstract class MovementTest : InteractionTest
|
||||
|
||||
for (var i = -Tiles; i <= Tiles; i++)
|
||||
{
|
||||
await SetTile(Plating, SEntMan.GetNetCoordinates(pCoords.Offset(new Vector2(i, 0))), MapData.MapGrid);
|
||||
await SetTile(Plating, SEntMan.GetNetCoordinates(pCoords.Offset(new Vector2(i, 0))), MapData.Grid.Comp);
|
||||
}
|
||||
AssertGridCount(1);
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Linter;
|
||||
|
||||
/// <summary>
|
||||
/// Verify that the yaml linter successfully validates static fields
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public sealed class StaticFieldValidationTest
|
||||
{
|
||||
[Test]
|
||||
public async Task TestStaticFieldValidation()
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient();
|
||||
var protoMan = pair.Server.ProtoMan;
|
||||
|
||||
var protos = new Dictionary<Type, HashSet<string>>();
|
||||
foreach (var kind in protoMan.EnumeratePrototypeKinds())
|
||||
{
|
||||
var ids = protoMan.EnumeratePrototypes(kind).Select(x => x.ID).ToHashSet();
|
||||
protos.Add(kind, ids);
|
||||
}
|
||||
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(StringValid), protos).Count, Is.Zero);
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(StringArrayValid), protos).Count, Is.Zero);
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(EntProtoIdValid), protos).Count, Is.Zero);
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(EntProtoIdArrayValid), protos).Count, Is.Zero);
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdTestValid), protos).Count, Is.Zero);
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdArrayValid), protos).Count, Is.Zero);
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdListValid), protos).Count, Is.Zero);
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdSetValid), protos).Count, Is.Zero);
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(PrivateProtoIdArrayValid), protos).Count, Is.Zero);
|
||||
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(StringInvalid), protos).Count, Is.EqualTo(1));
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(StringArrayInvalid), protos).Count, Is.EqualTo(2));
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(EntProtoIdInvalid), protos).Count, Is.EqualTo(1));
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(EntProtoIdArrayInvalid), protos).Count, Is.EqualTo(2));
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdTestInvalid), protos).Count, Is.EqualTo(1));
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdArrayInvalid), protos).Count, Is.EqualTo(2));
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdListInvalid), protos).Count, Is.EqualTo(2));
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdSetInvalid), protos).Count, Is.EqualTo(2));
|
||||
Assert.That(protoMan.ValidateStaticFields(typeof(PrivateProtoIdArrayInvalid), protos).Count, Is.EqualTo(2));
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
[TestPrototypes]
|
||||
private const string TestPrototypes = @"
|
||||
- type: entity
|
||||
id: StaticFieldTestEnt
|
||||
|
||||
- type: Tag
|
||||
id: StaticFieldTestTag
|
||||
";
|
||||
|
||||
[Reflect(false)] private sealed class StringValid
|
||||
{
|
||||
[ValidatePrototypeId<TagPrototype>] public static string Tag = "StaticFieldTestTag";
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class StringInvalid
|
||||
{
|
||||
[ValidatePrototypeId<TagPrototype>] public static string Tag = string.Empty;
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class StringArrayValid
|
||||
{
|
||||
[ValidatePrototypeId<TagPrototype>] public static string[] Tag = {"StaticFieldTestTag", "StaticFieldTestTag"};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class StringArrayInvalid
|
||||
{
|
||||
[ValidatePrototypeId<TagPrototype>] public static string[] Tag = {string.Empty, "StaticFieldTestTag", string.Empty};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class EntProtoIdValid
|
||||
{
|
||||
public static EntProtoId Tag = "StaticFieldTestEnt";
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class EntProtoIdInvalid
|
||||
{
|
||||
public static EntProtoId Tag = string.Empty;
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class EntProtoIdArrayValid
|
||||
{
|
||||
public static EntProtoId[] Tag = {"StaticFieldTestEnt", "StaticFieldTestEnt"};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class EntProtoIdArrayInvalid
|
||||
{
|
||||
public static EntProtoId[] Tag = {string.Empty, "StaticFieldTestEnt", string.Empty};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class ProtoIdTestValid
|
||||
{
|
||||
public static ProtoId<TagPrototype> Tag = "StaticFieldTestTag";
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class ProtoIdTestInvalid
|
||||
{
|
||||
public static ProtoId<TagPrototype> Tag = string.Empty;
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class ProtoIdArrayValid
|
||||
{
|
||||
public static ProtoId<TagPrototype>[] Tag = {"StaticFieldTestTag", "StaticFieldTestTag"};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class ProtoIdArrayInvalid
|
||||
{
|
||||
public static ProtoId<TagPrototype>[] Tag = {string.Empty, "StaticFieldTestTag", string.Empty};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class ProtoIdListValid
|
||||
{
|
||||
public static List<ProtoId<TagPrototype>> Tag = new() {"StaticFieldTestTag", "StaticFieldTestTag"};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class ProtoIdListInvalid
|
||||
{
|
||||
public static List<ProtoId<TagPrototype>> Tag = new() {string.Empty, "StaticFieldTestTag", string.Empty};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class ProtoIdSetValid
|
||||
{
|
||||
public static HashSet<ProtoId<TagPrototype>> Tag = new() {"StaticFieldTestTag", "StaticFieldTestTag"};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class ProtoIdSetInvalid
|
||||
{
|
||||
public static HashSet<ProtoId<TagPrototype>> Tag = new() {string.Empty, "StaticFieldTestTag", string.Empty, " "};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class PrivateProtoIdArrayValid
|
||||
{
|
||||
private static ProtoId<TagPrototype>[] Tag = {"StaticFieldTestTag", "StaticFieldTestTag"};
|
||||
}
|
||||
|
||||
[Reflect(false)] private sealed class PrivateProtoIdArrayInvalid
|
||||
{
|
||||
private static ProtoId<TagPrototype>[] Tag = {string.Empty, "StaticFieldTestTag", string.Empty};
|
||||
}
|
||||
}
|
||||
102
Content.IntegrationTests/Tests/Mapping/MappingTests.cs
Normal file
102
Content.IntegrationTests/Tests/Mapping/MappingTests.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Mapping;
|
||||
|
||||
[TestFixture]
|
||||
public sealed class MappingTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks that the mapping command creates paused & uninitialized maps.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task MappingTest()
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient(new PoolSettings {Dirty = true, Connected = true, DummyTicker = false});
|
||||
|
||||
var server = pair.Server;
|
||||
var entMan = server.EntMan;
|
||||
var mapSys = server.System<MapSystem>();
|
||||
|
||||
await pair.RunTicksSync(5);
|
||||
var mapId = 1;
|
||||
while (mapSys.MapExists(new(mapId)))
|
||||
{
|
||||
mapId++;
|
||||
}
|
||||
|
||||
await pair.WaitClientCommand($"mapping {mapId}");
|
||||
var map = mapSys.GetMap(new MapId(mapId));
|
||||
|
||||
var mapXform = server.Transform(map);
|
||||
Assert.That(mapXform.MapUid, Is.EqualTo(map));
|
||||
Assert.That(mapXform.MapID, Is.EqualTo(new MapId(mapId)));
|
||||
|
||||
var xform = server.Transform(pair.Player!.AttachedEntity!.Value);
|
||||
|
||||
Assert.That(xform.MapUid, Is.EqualTo(map));
|
||||
Assert.That(mapSys.IsInitialized(map), Is.False);
|
||||
Assert.That(mapSys.IsPaused(map), Is.True);
|
||||
Assert.That(server.MetaData(map).EntityLifeStage, Is.EqualTo(EntityLifeStage.Initialized));
|
||||
Assert.That(server.MetaData(map).EntityPaused, Is.True);
|
||||
|
||||
// Spawn a new entity
|
||||
EntityUid ent = default;
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
ent = entMan.Spawn(null, new MapCoordinates(default, new(mapId)));
|
||||
});
|
||||
await pair.RunTicksSync(5);
|
||||
Assert.That(server.MetaData(ent).EntityLifeStage, Is.EqualTo(EntityLifeStage.Initialized));
|
||||
Assert.That(server.MetaData(ent).EntityPaused, Is.True);
|
||||
|
||||
// Save the map
|
||||
var file = $"{nameof(MappingTest)}.yml";
|
||||
await pair.WaitClientCommand($"savemap {mapId} {file}");
|
||||
|
||||
// Mapinitialize it
|
||||
await pair.WaitClientCommand($"mapinit {mapId}");
|
||||
Assert.That(mapSys.IsInitialized(map), Is.True);
|
||||
Assert.That(mapSys.IsPaused(map), Is.False);
|
||||
Assert.That(server.MetaData(map).EntityLifeStage, Is.EqualTo(EntityLifeStage.MapInitialized));
|
||||
Assert.That(server.MetaData(map).EntityPaused, Is.False);
|
||||
Assert.That(server.MetaData(ent).EntityLifeStage, Is.EqualTo(EntityLifeStage.MapInitialized));
|
||||
Assert.That(server.MetaData(ent).EntityPaused, Is.False);
|
||||
|
||||
await server.WaitPost(() => entMan.DeleteEntity(map));
|
||||
|
||||
// Load the saved map
|
||||
mapId++;
|
||||
while (mapSys.MapExists(new(mapId)))
|
||||
{
|
||||
mapId++;
|
||||
}
|
||||
|
||||
await pair.WaitClientCommand($"mapping {mapId} {file}");
|
||||
map = mapSys.GetMap(new MapId(mapId));
|
||||
|
||||
// And it should all be paused and un-initialized
|
||||
xform = server.Transform(pair.Player!.AttachedEntity!.Value);
|
||||
Assert.That(xform.MapUid, Is.EqualTo(map));
|
||||
Assert.That(mapSys.IsInitialized(map), Is.False);
|
||||
Assert.That(mapSys.IsPaused(map), Is.True);
|
||||
Assert.That(server.MetaData(map).EntityLifeStage, Is.EqualTo(EntityLifeStage.Initialized));
|
||||
Assert.That(server.MetaData(map).EntityPaused, Is.True);
|
||||
|
||||
mapXform = server.Transform(map);
|
||||
Assert.That(mapXform.MapUid, Is.EqualTo(map));
|
||||
Assert.That(mapXform.MapID, Is.EqualTo(new MapId(mapId)));
|
||||
Assert.That(mapXform.ChildCount, Is.EqualTo(2));
|
||||
|
||||
mapXform.ChildEnumerator.MoveNext(out ent);
|
||||
if (ent == pair.Player.AttachedEntity)
|
||||
mapXform.ChildEnumerator.MoveNext(out ent);
|
||||
|
||||
Assert.That(server.MetaData(ent).EntityLifeStage, Is.EqualTo(EntityLifeStage.Initialized));
|
||||
Assert.That(server.MetaData(ent).EntityPaused, Is.True);
|
||||
|
||||
await server.WaitPost(() => entMan.DeleteEntity(map));
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Cargo.Systems;
|
||||
using Content.Server.Construction.Completions;
|
||||
using Content.Server.Construction.Components;
|
||||
using Content.Server.Destructible;
|
||||
using Content.Server.Destructible.Thresholds.Behaviors;
|
||||
using Content.Server.Stack;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Construction.Components;
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Content.Shared.Construction.Steps;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Construction.Components;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Materials;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.IntegrationTests.Tests;
|
||||
|
||||
@@ -52,10 +53,10 @@ public sealed class MaterialArbitrageTest
|
||||
var destructibleName = compFact.GetComponentName(typeof(DestructibleComponent));
|
||||
|
||||
// construct inverted lathe recipe dictionary
|
||||
Dictionary<string, LatheRecipePrototype> latheRecipes = new();
|
||||
Dictionary<string, List<LatheRecipePrototype>> latheRecipes = new();
|
||||
foreach (var proto in protoManager.EnumeratePrototypes<LatheRecipePrototype>())
|
||||
{
|
||||
latheRecipes.Add(proto.Result, proto);
|
||||
latheRecipes.GetOrNew(proto.Result).Add(proto);
|
||||
}
|
||||
|
||||
// Lets assume the possible lathe for resource multipliers:
|
||||
@@ -183,16 +184,19 @@ public sealed class MaterialArbitrageTest
|
||||
var spawnedPrice = await GetSpawnedPrice(spawnedEnts);
|
||||
var price = await GetPrice(id);
|
||||
if (spawnedPrice > 0 && price > 0)
|
||||
Assert.That(spawnedPrice, Is.LessThanOrEqualTo(price), $"{id} increases in price after being destroyed");
|
||||
Assert.That(spawnedPrice, Is.LessThanOrEqualTo(price), $"{id} increases in price after being destroyed\nEntities spawned on destruction: {string.Join(',', spawnedEnts)}");
|
||||
|
||||
// Check lathe production
|
||||
if (latheRecipes.TryGetValue(id, out var recipe))
|
||||
if (latheRecipes.TryGetValue(id, out var recipes))
|
||||
{
|
||||
foreach (var (matId, amount) in recipe.RequiredMaterials)
|
||||
foreach (var recipe in recipes)
|
||||
{
|
||||
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
|
||||
if (spawnedMats.TryGetValue(matId, out var numSpawned))
|
||||
Assert.That(numSpawned, Is.LessThanOrEqualTo(actualAmount), $"destroying a {id} spawns more {matId} than required to produce via an (upgraded) lathe.");
|
||||
foreach (var (matId, amount) in recipe.RequiredMaterials)
|
||||
{
|
||||
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
|
||||
if (spawnedMats.TryGetValue(matId, out var numSpawned))
|
||||
Assert.That(numSpawned, Is.LessThanOrEqualTo(actualAmount), $"destroying a {id} spawns more {matId} than required to produce via an (upgraded) lathe.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,13 +267,16 @@ public sealed class MaterialArbitrageTest
|
||||
Assert.That(deconstructedPrice, Is.LessThanOrEqualTo(price), $"{id} increases in price after being deconstructed");
|
||||
|
||||
// Check lathe production
|
||||
if (latheRecipes.TryGetValue(id, out var recipe))
|
||||
if (latheRecipes.TryGetValue(id, out var recipes))
|
||||
{
|
||||
foreach (var (matId, amount) in recipe.RequiredMaterials)
|
||||
foreach (var recipe in recipes)
|
||||
{
|
||||
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
|
||||
if (deconstructedMats.TryGetValue(matId, out var numSpawned))
|
||||
Assert.That(numSpawned, Is.LessThanOrEqualTo(actualAmount), $"deconstructing {id} spawns more {matId} than required to produce via an (upgraded) lathe.");
|
||||
foreach (var (matId, amount) in recipe.RequiredMaterials)
|
||||
{
|
||||
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
|
||||
if (deconstructedMats.TryGetValue(matId, out var numSpawned))
|
||||
Assert.That(numSpawned, Is.LessThanOrEqualTo(actualAmount), $"deconstructing {id} spawns more {matId} than required to produce via an (upgraded) lathe.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,13 +322,16 @@ public sealed class MaterialArbitrageTest
|
||||
Assert.That(sumPrice, Is.LessThanOrEqualTo(price), $"{id} increases in price after decomposed into raw materials");
|
||||
|
||||
// Check lathe production
|
||||
if (latheRecipes.TryGetValue(id, out var recipe))
|
||||
if (latheRecipes.TryGetValue(id, out var recipes))
|
||||
{
|
||||
foreach (var (matId, amount) in recipe.RequiredMaterials)
|
||||
foreach (var recipe in recipes)
|
||||
{
|
||||
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
|
||||
if (compositionComponent.MaterialComposition.TryGetValue(matId, out var numSpawned))
|
||||
Assert.That(numSpawned, Is.LessThanOrEqualTo(actualAmount), $"The physical composition of {id} has more {matId} than required to produce via an (upgraded) lathe.");
|
||||
foreach (var (matId, amount) in recipe.RequiredMaterials)
|
||||
{
|
||||
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
|
||||
if (compositionComponent.MaterialComposition.TryGetValue(matId, out var numSpawned))
|
||||
Assert.That(numSpawned, Is.LessThanOrEqualTo(actualAmount), $"The physical composition of {id} has more {matId} than required to produce via an (upgraded) lathe.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +369,7 @@ public sealed class MaterialArbitrageTest
|
||||
{
|
||||
var ent = entManager.SpawnEntity(id, testMap.GridCoords);
|
||||
stackSys.SetCount(ent, 1);
|
||||
priceCache[id] = price = pricing.GetPrice(ent);
|
||||
priceCache[id] = price = pricing.GetPrice(ent, false);
|
||||
entManager.DeleteEntity(ent);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -45,32 +45,11 @@ namespace Content.IntegrationTests.Tests
|
||||
private static readonly string[] GameMaps =
|
||||
{
|
||||
"Dev",
|
||||
"TestTeg",
|
||||
"Fland",
|
||||
"Meta",
|
||||
"Packed",
|
||||
"Cluster",
|
||||
"Omega",
|
||||
"Bagel",
|
||||
"Origin",
|
||||
"CentComm",
|
||||
"NukieOutpost",
|
||||
"Box",
|
||||
"Europa",
|
||||
"Saltern",
|
||||
"Core",
|
||||
"Marathon",
|
||||
"MeteorArena",
|
||||
"Atlas",
|
||||
"Reach",
|
||||
"Train",
|
||||
"Atom",
|
||||
"DryDock",
|
||||
"Polaris",
|
||||
"Scoupidia",
|
||||
"Triumph",
|
||||
"Void",
|
||||
"WonderBox"
|
||||
"WonderBox",
|
||||
"WhiteBox",
|
||||
"WhiteMoose"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -165,7 +144,10 @@ namespace Content.IntegrationTests.Tests
|
||||
[Test, TestCaseSource(nameof(GameMaps))]
|
||||
public async Task GameMapsLoadableTest(string mapProto)
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient();
|
||||
await using var pair = await PoolManager.GetServerClient(new PoolSettings
|
||||
{
|
||||
Dirty = true // Stations spawn a bunch of nullspace entities and maps like centcomm.
|
||||
});
|
||||
var server = pair.Server;
|
||||
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
@@ -399,4 +381,4 @@ namespace Content.IntegrationTests.Tests
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ namespace Content.IntegrationTests.Tests.Power
|
||||
anchored: true
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ApcUiKey.Key
|
||||
type: ApcBoundUserInterface
|
||||
enum.ApcUiKey.Key:
|
||||
type: ApcBoundUserInterface
|
||||
- type: AccessReader
|
||||
access: [['Engineering']]
|
||||
|
||||
|
||||
@@ -38,31 +38,15 @@ public sealed class PrototypeSaveTest
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var entityMan = server.ResolveDependency<IEntityManager>();
|
||||
var prototypeMan = server.ResolveDependency<IPrototypeManager>();
|
||||
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
|
||||
var seriMan = server.ResolveDependency<ISerializationManager>();
|
||||
var compFact = server.ResolveDependency<IComponentFactory>();
|
||||
|
||||
var prototypes = new List<EntityPrototype>();
|
||||
MapGridComponent grid = default!;
|
||||
EntityUid uid;
|
||||
MapId mapId = default;
|
||||
|
||||
//Build up test environment
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
// Create a one tile grid to stave off the grid 0 monsters
|
||||
mapId = mapManager.CreateMap();
|
||||
|
||||
mapManager.AddUninitializedMap(mapId);
|
||||
|
||||
grid = mapManager.CreateGrid(mapId);
|
||||
|
||||
var tileDefinition = tileDefinitionManager["FloorSteel"]; // Wires n such disable ambiance while under the floor
|
||||
var tile = new Tile(tileDefinition.TileId);
|
||||
var coordinates = grid.Owner.ToCoordinates();
|
||||
|
||||
grid.SetTile(coordinates, tile);
|
||||
});
|
||||
await pair.CreateTestMap(false, "FloorSteel"); // Wires n such disable ambiance while under the floor
|
||||
var mapId = pair.TestMap.MapId;
|
||||
var grid = pair.TestMap.Grid;
|
||||
|
||||
await server.WaitRunTicks(5);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Content.IntegrationTests.Tests
|
||||
{
|
||||
private sealed class RoundEndTestSystem : EntitySystem
|
||||
{
|
||||
public int Count;
|
||||
public int RoundCount;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -22,7 +22,7 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
private void OnRoundEnd(RoundEndSystemChangedEvent ev)
|
||||
{
|
||||
Interlocked.Increment(ref Count);
|
||||
Interlocked.Increment(ref RoundCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Content.IntegrationTests.Tests
|
||||
var ticker = sysManager.GetEntitySystem<GameTicker>();
|
||||
var roundEndSystem = sysManager.GetEntitySystem<RoundEndSystem>();
|
||||
var sys = server.System<RoundEndTestSystem>();
|
||||
sys.Count = 0;
|
||||
sys.RoundCount = 0;
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
@@ -128,8 +128,8 @@ namespace Content.IntegrationTests.Tests
|
||||
async Task WaitForEvent()
|
||||
{
|
||||
var timeout = Task.Delay(TimeSpan.FromSeconds(10));
|
||||
var currentCount = Thread.VolatileRead(ref sys.Count);
|
||||
while (currentCount == Thread.VolatileRead(ref sys.Count) && !timeout.IsCompleted)
|
||||
var currentCount = Thread.VolatileRead(ref sys.RoundCount);
|
||||
while (currentCount == Thread.VolatileRead(ref sys.RoundCount) && !timeout.IsCompleted)
|
||||
{
|
||||
await pair.RunTicksSync(5);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public sealed class DockTest : ContentUnitTest
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
entManager.DeleteEntity(map.GridUid);
|
||||
entManager.DeleteEntity(map.Grid);
|
||||
var grid1 = mapManager.CreateGridEntity(mapId);
|
||||
var grid2 = mapManager.CreateGridEntity(mapId);
|
||||
var grid1Ent = grid1.Owner;
|
||||
@@ -104,7 +104,7 @@ public sealed class DockTest : ContentUnitTest
|
||||
// Spawn shuttle and affirm no valid docks.
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
entManager.DeleteEntity(map.GridUid);
|
||||
entManager.DeleteEntity(map.Grid);
|
||||
Assert.That(entManager.System<MapLoaderSystem>().TryLoad(otherMap.MapId, "/Maps/Shuttles/emergency.yml", out var rootUids));
|
||||
shuttle = rootUids[0];
|
||||
|
||||
|
||||
127
Content.IntegrationTests/Tests/Station/EvacShuttleTest.cs
Normal file
127
Content.IntegrationTests/Tests/Station/EvacShuttleTest.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System.Linq;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Shuttles.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map.Components;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Station;
|
||||
|
||||
[TestFixture]
|
||||
[TestOf(typeof(EmergencyShuttleSystem))]
|
||||
public sealed class EvacShuttleTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensure that the emergency shuttle can be called, and that it will travel to centcomm
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task EmergencyEvacTest()
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient(new PoolSettings { DummyTicker = true, Dirty = true });
|
||||
var server = pair.Server;
|
||||
var entMan = server.EntMan;
|
||||
var ticker = server.System<GameTicker>();
|
||||
|
||||
// Dummy ticker tests should not have centcomm
|
||||
Assert.That(entMan.Count<StationCentcommComponent>(), Is.Zero);
|
||||
|
||||
Assert.That(pair.Server.CfgMan.GetCVar(CCVars.GridFill), Is.False);
|
||||
pair.Server.CfgMan.SetCVar(CCVars.EmergencyShuttleEnabled, true);
|
||||
pair.Server.CfgMan.SetCVar(CCVars.GameDummyTicker, false);
|
||||
var gameMap = pair.Server.CfgMan.GetCVar(CCVars.GameMap);
|
||||
pair.Server.CfgMan.SetCVar(CCVars.GameMap, "Saltern");
|
||||
|
||||
await server.WaitPost(() => ticker.RestartRound());
|
||||
await pair.RunTicksSync(25);
|
||||
Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
|
||||
|
||||
// Find the station, centcomm, and shuttle, and ftl map.
|
||||
|
||||
Assert.That(entMan.Count<StationCentcommComponent>(), Is.EqualTo(1));
|
||||
Assert.That(entMan.Count<StationEmergencyShuttleComponent>(), Is.EqualTo(1));
|
||||
Assert.That(entMan.Count<StationDataComponent>(), Is.EqualTo(1));
|
||||
Assert.That(entMan.Count<EmergencyShuttleComponent>(), Is.EqualTo(1));
|
||||
Assert.That(entMan.Count<FTLMapComponent>(), Is.EqualTo(0));
|
||||
|
||||
var station = (Entity<StationCentcommComponent>) entMan.AllComponentsList<StationCentcommComponent>().Single();
|
||||
var data = entMan.GetComponent<StationDataComponent>(station);
|
||||
var shuttleData = entMan.GetComponent<StationEmergencyShuttleComponent>(station);
|
||||
|
||||
var saltern = data.Grids.Single();
|
||||
Assert.That(entMan.HasComponent<MapGridComponent>(saltern));
|
||||
|
||||
var shuttle = shuttleData.EmergencyShuttle!.Value;
|
||||
Assert.That(entMan.HasComponent<EmergencyShuttleComponent>(shuttle));
|
||||
Assert.That(entMan.HasComponent<MapGridComponent>(shuttle));
|
||||
|
||||
var centcomm = station.Comp.Entity!.Value;
|
||||
Assert.That(entMan.HasComponent<MapGridComponent>(centcomm));
|
||||
|
||||
var centcommMap = station.Comp.MapEntity!.Value;
|
||||
Assert.That(entMan.HasComponent<MapComponent>(centcommMap));
|
||||
Assert.That(server.Transform(centcomm).MapUid, Is.EqualTo(centcommMap));
|
||||
|
||||
var salternXform = server.Transform(saltern);
|
||||
Assert.That(salternXform.MapUid, Is.Not.Null);
|
||||
Assert.That(salternXform.MapUid, Is.Not.EqualTo(centcommMap));
|
||||
|
||||
var shuttleXform = server.Transform(shuttle);
|
||||
Assert.That(shuttleXform.MapUid, Is.Not.Null);
|
||||
Assert.That(shuttleXform.MapUid, Is.EqualTo(centcommMap));
|
||||
|
||||
// All of these should have been map-initialized.
|
||||
var mapSys = entMan.System<SharedMapSystem>();
|
||||
Assert.That(mapSys.IsInitialized(centcommMap), Is.True);
|
||||
Assert.That(mapSys.IsInitialized(salternXform.MapUid), Is.True);
|
||||
Assert.That(mapSys.IsPaused(centcommMap), Is.False);
|
||||
Assert.That(mapSys.IsPaused(salternXform.MapUid!.Value), Is.False);
|
||||
|
||||
EntityLifeStage LifeStage(EntityUid uid) => entMan.GetComponent<MetaDataComponent>(uid).EntityLifeStage;
|
||||
Assert.That(LifeStage(saltern), Is.EqualTo(EntityLifeStage.MapInitialized));
|
||||
Assert.That(LifeStage(shuttle), Is.EqualTo(EntityLifeStage.MapInitialized));
|
||||
Assert.That(LifeStage(centcomm), Is.EqualTo(EntityLifeStage.MapInitialized));
|
||||
Assert.That(LifeStage(centcommMap), Is.EqualTo(EntityLifeStage.MapInitialized));
|
||||
Assert.That(LifeStage(salternXform.MapUid.Value), Is.EqualTo(EntityLifeStage.MapInitialized));
|
||||
|
||||
// Set up shuttle timing
|
||||
var shuttleSys = server.System<ShuttleSystem>();
|
||||
var evacSys = server.System<EmergencyShuttleSystem>();
|
||||
evacSys.TransitTime = shuttleSys.DefaultTravelTime; // Absolute minimum transit time, so the test has to run for at least this long
|
||||
// TODO SHUTTLE fix spaghetti
|
||||
|
||||
var dockTime = server.CfgMan.GetCVar(CCVars.EmergencyShuttleDockTime);
|
||||
server.CfgMan.SetCVar(CCVars.EmergencyShuttleDockTime, 2);
|
||||
|
||||
// Call evac shuttle.
|
||||
await pair.WaitCommand("callshuttle 0:02");
|
||||
await pair.RunSeconds(3);
|
||||
|
||||
// Shuttle should have arrived on the station
|
||||
Assert.That(shuttleXform.MapUid, Is.EqualTo(salternXform.MapUid));
|
||||
|
||||
await pair.RunSeconds(2);
|
||||
|
||||
// Shuttle should be FTLing back to centcomm
|
||||
Assert.That(entMan.Count<FTLMapComponent>(), Is.EqualTo(1));
|
||||
var ftl = (Entity<FTLMapComponent>) entMan.AllComponentsList<FTLMapComponent>().Single();
|
||||
Assert.That(entMan.HasComponent<MapComponent>(ftl));
|
||||
Assert.That(ftl.Owner, Is.Not.EqualTo(centcommMap));
|
||||
Assert.That(ftl.Owner, Is.Not.EqualTo(salternXform.MapUid));
|
||||
Assert.That(shuttleXform.MapUid, Is.EqualTo(ftl.Owner));
|
||||
|
||||
// Shuttle should have arrived at centcomm
|
||||
await pair.RunSeconds(shuttleSys.DefaultTravelTime);
|
||||
Assert.That(shuttleXform.MapUid, Is.EqualTo(centcommMap));
|
||||
|
||||
// Round should be ending now
|
||||
Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.PostRound));
|
||||
|
||||
server.CfgMan.SetCVar(CCVars.EmergencyShuttleDockTime, dockTime);
|
||||
pair.Server.CfgMan.SetCVar(CCVars.EmergencyShuttleEnabled, false);
|
||||
pair.Server.CfgMan.SetCVar(CCVars.GameMap, gameMap);
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
}
|
||||
@@ -92,23 +92,32 @@ namespace Content.IntegrationTests.Tests
|
||||
var allSizes = protoMan.EnumeratePrototypes<ItemSizePrototype>().ToList();
|
||||
allSizes.Sort();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
await Assert.MultipleAsync(async () =>
|
||||
{
|
||||
foreach (var proto in pair.GetPrototypesWithComponent<StorageFillComponent>())
|
||||
{
|
||||
if (proto.HasComponent<EntityStorageComponent>(compFact))
|
||||
continue;
|
||||
|
||||
if (!proto.TryGetComponent<StorageComponent>("Storage", out var storage))
|
||||
StorageComponent? storage = null;
|
||||
ItemComponent? item = null;
|
||||
StorageFillComponent fill = default!;
|
||||
var size = 0;
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
Assert.Fail($"Entity {proto.ID} has storage-fill without a storage component!");
|
||||
if (!proto.TryGetComponent("Storage", out storage))
|
||||
{
|
||||
Assert.Fail($"Entity {proto.ID} has storage-fill without a storage component!");
|
||||
return;
|
||||
}
|
||||
|
||||
proto.TryGetComponent("Item", out item);
|
||||
fill = (StorageFillComponent) proto.Components[id].Component;
|
||||
size = GetFillSize(fill, false, protoMan, itemSys);
|
||||
});
|
||||
|
||||
if (storage == null)
|
||||
continue;
|
||||
}
|
||||
|
||||
proto.TryGetComponent<ItemComponent>("Item", out var item);
|
||||
|
||||
var fill = (StorageFillComponent) proto.Components[id].Component;
|
||||
var size = GetFillSize(fill, false, protoMan, itemSys);
|
||||
|
||||
var maxSize = storage.MaxItemSize;
|
||||
if (storage.MaxItemSize == null)
|
||||
@@ -138,7 +147,13 @@ namespace Content.IntegrationTests.Tests
|
||||
if (!protoMan.TryIndex<EntityPrototype>(entry.PrototypeId, out var fillItem))
|
||||
continue;
|
||||
|
||||
if (!fillItem.TryGetComponent<ItemComponent>("Item", out var entryItem))
|
||||
ItemComponent? entryItem = null;
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
fillItem.TryGetComponent("Item", out entryItem);
|
||||
});
|
||||
|
||||
if (entryItem == null)
|
||||
continue;
|
||||
|
||||
Assert.That(protoMan.Index(entryItem.Size).Weight,
|
||||
@@ -164,25 +179,25 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
var itemSys = entMan.System<SharedItemSystem>();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
foreach (var proto in pair.GetPrototypesWithComponent<StorageFillComponent>())
|
||||
{
|
||||
foreach (var proto in pair.GetPrototypesWithComponent<StorageFillComponent>())
|
||||
{
|
||||
if (proto.HasComponent<StorageComponent>(compFact))
|
||||
continue;
|
||||
if (proto.HasComponent<StorageComponent>(compFact))
|
||||
continue;
|
||||
|
||||
if (!proto.TryGetComponent<EntityStorageComponent>("EntityStorage", out var entStorage))
|
||||
{
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
if (!proto.TryGetComponent("EntityStorage", out EntityStorageComponent? entStorage))
|
||||
Assert.Fail($"Entity {proto.ID} has storage-fill without a storage component!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entStorage == null)
|
||||
return;
|
||||
|
||||
var fill = (StorageFillComponent) proto.Components[id].Component;
|
||||
var size = GetFillSize(fill, true, protoMan, itemSys);
|
||||
Assert.That(size, Is.LessThanOrEqualTo(entStorage.Capacity),
|
||||
$"{proto.ID} storage fill is too large.");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public sealed class TileConstructionTests : InteractionTest
|
||||
// Remove grid
|
||||
await SetTile(null);
|
||||
await SetTile(null, PlayerCoords);
|
||||
Assert.That(MapData.MapGrid.Deleted);
|
||||
Assert.That(MapData.Grid.Comp.Deleted);
|
||||
AssertGridCount(0);
|
||||
|
||||
// Place Lattice
|
||||
@@ -70,7 +70,7 @@ public sealed class TileConstructionTests : InteractionTest
|
||||
// Remove grid
|
||||
await SetTile(null);
|
||||
await SetTile(null, PlayerCoords);
|
||||
Assert.That(MapData.MapGrid.Deleted);
|
||||
Assert.That(MapData.Grid.Comp.Deleted);
|
||||
AssertGridCount(0);
|
||||
|
||||
// Space -> Lattice
|
||||
|
||||
@@ -64,7 +64,8 @@ namespace Content.IntegrationTests.Tests.Utility
|
||||
var testMap = await pair.CreateTestMap();
|
||||
var mapCoordinates = testMap.MapCoords;
|
||||
|
||||
var sEntities = server.ResolveDependency<IEntityManager>();
|
||||
var sEntities = server.EntMan;
|
||||
var sys = server.System<EntityWhitelistSystem>();
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
@@ -80,22 +81,14 @@ namespace Content.IntegrationTests.Tests.Utility
|
||||
Components = new[] { $"{ValidComponent}" },
|
||||
Tags = new() { "WhitelistTestValidTag" }
|
||||
};
|
||||
whitelistInst.UpdateRegistrations();
|
||||
Assert.That(whitelistInst, Is.Not.Null);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(whitelistInst.Components, Is.Not.Null);
|
||||
Assert.That(whitelistInst.Tags, Is.Not.Null);
|
||||
});
|
||||
Assert.That(sys.IsValid(whitelistInst, validComponent), Is.True);
|
||||
Assert.That(sys.IsValid(whitelistInst, WhitelistTestValidTag), Is.True);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(whitelistInst.IsValid(validComponent), Is.True);
|
||||
Assert.That(whitelistInst.IsValid(WhitelistTestValidTag), Is.True);
|
||||
|
||||
Assert.That(whitelistInst.IsValid(invalidComponent), Is.False);
|
||||
Assert.That(whitelistInst.IsValid(WhitelistTestInvalidTag), Is.False);
|
||||
Assert.That(sys.IsValid(whitelistInst, invalidComponent), Is.False);
|
||||
Assert.That(sys.IsValid(whitelistInst, WhitelistTestInvalidTag), Is.False);
|
||||
});
|
||||
|
||||
// Test from serialized
|
||||
@@ -111,11 +104,11 @@ namespace Content.IntegrationTests.Tests.Utility
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(whitelistSer.IsValid(validComponent), Is.True);
|
||||
Assert.That(whitelistSer.IsValid(WhitelistTestValidTag), Is.True);
|
||||
Assert.That(sys.IsValid(whitelistSer, validComponent), Is.True);
|
||||
Assert.That(sys.IsValid(whitelistSer, WhitelistTestValidTag), Is.True);
|
||||
|
||||
Assert.That(whitelistSer.IsValid(invalidComponent), Is.False);
|
||||
Assert.That(whitelistSer.IsValid(WhitelistTestInvalidTag), Is.False);
|
||||
Assert.That(sys.IsValid(whitelistSer, invalidComponent), Is.False);
|
||||
Assert.That(sys.IsValid(whitelistSer, WhitelistTestInvalidTag), Is.False);
|
||||
});
|
||||
});
|
||||
await pair.CleanReturnAsync();
|
||||
|
||||
Reference in New Issue
Block a user