Merge remote-tracking branch 'upstream/stable' into ed-27-05-2025-upstream-sync

# Conflicts:
#	.github/CODEOWNERS
#	Content.Client/Guidebook/Controls/GuideReagentReaction.xaml.cs
#	Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs
#	Content.Server/Procedural/DungeonJob/DungeonJob.OreDunGen.cs
#	Resources/Prototypes/Entities/Effects/chemistry_effects.yml
#	Resources/Prototypes/Entities/Mobs/Customization/Markings/human_hair.yml
#	Resources/Prototypes/GameRules/meteorswarms.yml
#	Resources/Prototypes/Procedural/dungeon_configs.yml
This commit is contained in:
Ed
2025-05-27 12:21:14 +03:00
1165 changed files with 76878 additions and 44718 deletions

View File

@@ -111,9 +111,16 @@ public sealed partial class TestPair
HashSet<string>? ignored = null,
bool ignoreAbstract = true,
bool ignoreTestPrototypes = true)
where T : IComponent
where T : IComponent, new()
{
var id = Server.ResolveDependency<IComponentFactory>().GetComponentName(typeof(T));
if (!Server.ResolveDependency<IComponentFactory>().TryGetRegistration<T>(out var reg)
&& !Client.ResolveDependency<IComponentFactory>().TryGetRegistration<T>(out reg))
{
Assert.Fail($"Unknown component: {typeof(T).Name}");
return new();
}
var id = reg.Name;
var list = new List<(EntityPrototype, T)>();
foreach (var proto in Server.ProtoMan.EnumeratePrototypes<EntityPrototype>())
{

View File

@@ -59,7 +59,6 @@ namespace Content.IntegrationTests.Tests.Chemistry
#pragma warning restore NUnit2045
}
//------------CP14 - improve test for alchemy
//Get all possible reactions with the current reagents
var possibleReactions = prototypeManager.EnumeratePrototypes<ReactionPrototype>()
.Where(x => x.Reactants.All(id => solution.Contents.Any(s => s.Reagent.Prototype == id.Key)))
@@ -84,7 +83,6 @@ namespace Content.IntegrationTests.Tests.Chemistry
}
//Now safe set the temperature and mix the reagents
//----------CP14 - improve test for alchemy end
solutionContainerSystem.SetTemperature(solutionEnt.Value, reactionPrototype.MinimumTemperature);
if (reactionPrototype.MixingCategories != null)

View File

@@ -53,6 +53,7 @@ namespace Content.IntegrationTests.Tests
var eyeManager = client.ResolveDependency<IEyeManager>();
var spriteQuery = clientEntManager.GetEntityQuery<SpriteComponent>();
var eye = client.ResolveDependency<IEyeManager>().CurrentEye;
var spriteSys = clientEntManager.System<SpriteSystem>();
var testMap = await pair.CreateTestMap();
@@ -73,7 +74,7 @@ namespace Content.IntegrationTests.Tests
await client.WaitPost(() =>
{
var sprite = spriteQuery.GetComponent(clientEnt);
sprite.Scale = new Vector2(scale, scale);
spriteSys.SetScale((clientEnt, sprite), new Vector2(scale, scale));
// these tests currently all assume player eye is 0
eyeManager.CurrentEye.Rotation = 0;

View File

@@ -103,7 +103,7 @@ namespace Content.IntegrationTests.Tests.Construction
var protoMan = server.ResolveDependency<IPrototypeManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
var name = compFact.GetComponentName(typeof(ConstructionComponent));
var name = compFact.GetComponentName<ConstructionComponent>();
Assert.Multiple(() =>
{
foreach (var proto in protoMan.EnumeratePrototypes<EntityPrototype>())

View File

@@ -0,0 +1,40 @@
using Content.Shared.Alert;
using Content.Shared.Mobs.Components;
namespace Content.IntegrationTests.Tests.Damageable;
public sealed class MobThresholdsTest
{
/// <summary>
/// Inspects every entity prototype with a <see cref="MobThresholdsComponent"/> and makes
/// sure that every possible mob state is mapped to an <see cref="AlertPrototype"/>.
/// </summary>
[Test]
public async Task ValidateMobThresholds()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entMan = server.EntMan;
var protoMan = server.ProtoMan;
var protos = pair.GetPrototypesWithComponent<MobThresholdsComponent>();
Assert.Multiple(() =>
{
foreach (var (proto, comp) in protos)
{
// See which mob states are mapped to alerts
var alertStates = comp.StateAlertDict.Keys;
// Check each mob state that this mob can be in
foreach (var (_, state) in comp.Thresholds)
{
// Make sure that an alert exists for each possible mob state
Assert.That(alertStates, Does.Contain(state), $"{proto.ID} does not have an alert state for mob state {state}");
}
}
});
await pair.CleanReturnAsync();
}
}

View File

@@ -0,0 +1,28 @@
using Content.Shared.Explosion;
namespace Content.IntegrationTests.Tests.Explosion;
public sealed class ExplosionPrototypeTest
{
[Test]
public async Task ValidateExplosionPrototypes()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entMan = server.EntMan;
var protoMan = server.ProtoMan;
var protos = protoMan.EnumeratePrototypes<ExplosionPrototype>();
Assert.Multiple(() =>
{
foreach (var proto in protos)
{
Assert.That(proto._tileBreakChance, Is.Not.Empty, $"Empty tile break chance definitions for explosion prototype: {proto.ID}");
Assert.That(proto._tileBreakChance, Has.Length.EqualTo(proto._tileBreakIntensity.Length), $"Malformed tile break chance definitions for explosion prototype: {proto.ID}");
}
});
await pair.CleanReturnAsync();
}
}

View File

@@ -77,7 +77,7 @@ public abstract partial class InteractionTest
StackComponent? stack = null;
await server.WaitPost(() =>
{
entProto.TryGetComponent(factory.GetComponentName(typeof(StackComponent)), out stack);
entProto.TryGetComponent(factory.GetComponentName<StackComponent>(), out stack);
});
if (stack != null)
@@ -107,7 +107,7 @@ public abstract partial class InteractionTest
StackComponent? stack = null;
await Server.WaitPost(() =>
{
entProto.TryGetComponent(Factory.GetComponentName(typeof(StackComponent)), out stack);
entProto.TryGetComponent(Factory.GetComponentName<StackComponent>(), out stack);
});
if (stack != null)

View File

@@ -134,7 +134,7 @@ public abstract partial class InteractionTest
StackComponent? stack = null;
await server.WaitPost(() =>
{
entProto.TryGetComponent(factory.GetComponentName(typeof(StackComponent)), out stack);
entProto.TryGetComponent(factory.GetComponentName<StackComponent>(), out stack);
});
if (stack == null)

View File

@@ -1,9 +1,7 @@
using System.Collections.Generic;
using Content.Client.Weapons.Ranged.Components;
using Content.Shared.Prototypes;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests;
@@ -16,41 +14,41 @@ public sealed class MagazineVisualsSpriteTest
[Test]
public async Task MagazineVisualsSpritesExist()
{
await using var pair = await PoolManager.GetServerClient();
await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true });
var client = pair.Client;
var protoMan = client.ResolveDependency<IPrototypeManager>();
var componentFactory = client.ResolveDependency<IComponentFactory>();
var toTest = new List<(int, string)>();
var protos = pair.GetPrototypesWithComponent<MagazineVisualsComponent>();
var spriteSys = client.System<SpriteSystem>();
await client.WaitAssertion(() =>
{
Assert.Multiple(() =>
{
foreach (var proto in protoMan.EnumeratePrototypes<EntityPrototype>())
foreach (var (proto, _) in protos)
{
if (proto.Abstract || pair.IsTestPrototype(proto))
continue;
var uid = client.EntMan.Spawn(proto.ID);
var visuals = client.EntMan.GetComponent<MagazineVisualsComponent>(uid);
if (!proto.TryGetComponent<MagazineVisualsComponent>(out var visuals, componentFactory))
continue;
Assert.That(proto.TryGetComponent<SpriteComponent>(out var sprite, componentFactory),
Assert.That(client.EntMan.TryGetComponent(uid, out SpriteComponent sprite),
@$"{proto.ID} has MagazineVisualsComponent but no SpriteComponent.");
Assert.That(proto.HasComponent<AppearanceComponent>(componentFactory),
Assert.That(client.EntMan.HasComponent<AppearanceComponent>(uid),
@$"{proto.ID} has MagazineVisualsComponent but no AppearanceComponent.");
var toTest = new List<(int, string)>();
if (sprite.LayerMapTryGet(GunVisualLayers.Mag, out var magLayerId))
toTest.Clear();
if (spriteSys.LayerMapTryGet((uid, sprite), GunVisualLayers.Mag, out var magLayerId, false))
toTest.Add((magLayerId, ""));
if (sprite.LayerMapTryGet(GunVisualLayers.MagUnshaded, out var magUnshadedLayerId))
if (spriteSys.LayerMapTryGet((uid, sprite), GunVisualLayers.MagUnshaded, out var magUnshadedLayerId, false))
toTest.Add((magUnshadedLayerId, "-unshaded"));
Assert.That(toTest, Is.Not.Empty,
Assert.That(
toTest,
Is.Not.Empty,
@$"{proto.ID} has MagazineVisualsComponent but no Mag or MagUnshaded layer map.");
var start = visuals.ZeroVisible ? 0 : 1;
foreach (var (id, midfix) in toTest)
{
Assert.That(sprite.TryGetLayer(id, out var layer));
Assert.That(spriteSys.TryGetLayer((uid, sprite), id, out var layer, false));
var rsi = layer.ActualRsi;
for (var i = start; i < visuals.MagSteps; i++)
{
@@ -63,6 +61,8 @@ public sealed class MagazineVisualsSpriteTest
var extraState = $"{visuals.MagState}{midfix}-{visuals.MagSteps}";
Assert.That(rsi.TryGetState(extraState, out _), Is.False,
@$"{proto.ID} has MagazineVisualsComponent with MagSteps = {visuals.MagSteps}, but more states exist!");
client.EntMan.DeleteEntity(uid);
}
}
});

View File

@@ -63,11 +63,11 @@ public sealed class MaterialArbitrageTest
Assert.That(mapSystem.IsInitialized(testMap.MapId));
var constructionName = compFact.GetComponentName(typeof(ConstructionComponent));
var compositionName = compFact.GetComponentName(typeof(PhysicalCompositionComponent));
var materialName = compFact.GetComponentName(typeof(MaterialComponent));
var destructibleName = compFact.GetComponentName(typeof(DestructibleComponent));
var refinableName = compFact.GetComponentName(typeof(ToolRefinableComponent));
var constructionName = compFact.GetComponentName<ConstructionComponent>();
var compositionName = compFact.GetComponentName<PhysicalCompositionComponent>();
var materialName = compFact.GetComponentName<MaterialComponent>();
var destructibleName = compFact.GetComponentName<DestructibleComponent>();
var refinableName = compFact.GetComponentName<ToolRefinableComponent>();
// get the inverted lathe recipe dictionary
var latheRecipes = latheSys.InverseRecipes;

View File

@@ -18,7 +18,7 @@ public sealed class RoleTests
{
await using var pair = await PoolManager.GetServerClient();
var jobComp = pair.Server.ResolveDependency<IComponentFactory>().GetComponentName(typeof(JobRoleComponent));
var jobComp = pair.Server.ResolveDependency<IComponentFactory>().GetComponentName<JobRoleComponent>();
Assert.Multiple(() =>
{
@@ -49,7 +49,7 @@ public sealed class RoleTests
{
await using var pair = await PoolManager.GetServerClient();
var mindCompId = pair.Server.ResolveDependency<IComponentFactory>().GetComponentName(typeof(MindRoleComponent));
var mindCompId = pair.Server.ResolveDependency<IComponentFactory>().GetComponentName<MindRoleComponent>();
Assert.Multiple(() =>
{
@@ -73,7 +73,7 @@ public sealed class RoleTests
await using var pair = await PoolManager.GetServerClient();
var refMan = pair.Server.ResolveDependency<IReflectionManager>();
var mindCompId = pair.Server.ResolveDependency<IComponentFactory>().GetComponentName(typeof(MindRoleComponent));
var mindCompId = pair.Server.ResolveDependency<IComponentFactory>().GetComponentName<MindRoleComponent>();
var compTypes = refMan.GetAllChildren(typeof(BaseMindRoleComponent))
.Append(typeof(RoleBriefingComponent))

View File

@@ -85,7 +85,7 @@ namespace Content.IntegrationTests.Tests
var entMan = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
var id = compFact.GetComponentName(typeof(StorageFillComponent));
var id = compFact.GetComponentName<StorageFillComponent>();
var itemSys = entMan.System<SharedItemSystem>();
@@ -173,7 +173,7 @@ namespace Content.IntegrationTests.Tests
var entMan = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
var id = compFact.GetComponentName(typeof(StorageFillComponent));
var id = compFact.GetComponentName<StorageFillComponent>();
var itemSys = entMan.System<SharedItemSystem>();