Merge remote-tracking branch 'upstream/master' into fucking-upstream

This commit is contained in:
Jabak
2024-08-24 13:13:56 +03:00
2222 changed files with 247186 additions and 50848 deletions

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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(() =>

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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;

View 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();
}
}

View File

@@ -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));

View File

@@ -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();

View File

@@ -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!);
});

View File

@@ -407,7 +407,6 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
await pair.CleanReturnAsync();
}
[Reflect(false)]
public sealed class TestInteractionSystem : EntitySystem
{
public EntityEventHandler<InteractUsingEvent>? InteractUsingEvent;

View File

@@ -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();

View File

@@ -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));

View File

@@ -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)

View File

@@ -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);

View File

@@ -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>();

View File

@@ -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);

View File

@@ -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};
}
}

View 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();
}
}

View File

@@ -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);
});
}

View File

@@ -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();
}
}
}
}

View File

@@ -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']]

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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];

View 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();
}
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();