Merge pull request #301 from crystallpunk-14/ed-05-07-2024-upstream

Upstream sync
This commit is contained in:
Ed
2024-07-04 19:46:27 +03:00
committed by GitHub
306 changed files with 7615 additions and 3792 deletions

View File

@@ -1,4 +0,0 @@
{
"omnisharp.analyzeOpenDocumentsOnly": true,
"dotnet.defaultSolution": "SpaceStation14.sln"
}

View File

@@ -1,3 +1,4 @@
using Content.Client.BarSign.Ui;
using Content.Shared.BarSign;
using Content.Shared.Power;
using Robust.Client.GameObjects;
@@ -8,6 +9,7 @@ namespace Content.Client.BarSign;
public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
public override void Initialize()
{
@@ -17,6 +19,9 @@ public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
private void OnAfterAutoHandleState(EntityUid uid, BarSignComponent component, ref AfterAutoHandleStateEvent args)
{
if (_ui.TryGetOpenUi<BarSignBoundUserInterface>(uid, BarSignUiKey.Key, out var bui))
bui.Update(component.Current);
UpdateAppearance(uid, component);
}
@@ -34,9 +39,9 @@ public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
if (powered
&& sign.Current != null
&& _prototypeManager.TryIndex(sign.Current, out BarSignPrototype? proto))
&& _prototypeManager.TryIndex(sign.Current, out var proto))
{
sprite.LayerSetState(0, proto.Icon);
sprite.LayerSetSprite(0, proto.Icon);
sprite.LayerSetShader(0, "unshaded");
}
else

View File

@@ -0,0 +1,50 @@
using System.Linq;
using Content.Shared.BarSign;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
namespace Content.Client.BarSign.Ui;
[UsedImplicitly]
public sealed class BarSignBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
private BarSignMenu? _menu;
protected override void Open()
{
base.Open();
var sign = EntMan.GetComponentOrNull<BarSignComponent>(Owner)?.Current is { } current
? _prototype.Index(current)
: null;
var allSigns = Shared.BarSign.BarSignSystem.GetAllBarSigns(_prototype)
.OrderBy(p => Loc.GetString(p.Name))
.ToList();
_menu = new(sign, allSigns);
_menu.OnSignSelected += id =>
{
SendMessage(new SetBarSignMessage(id));
};
_menu.OnClose += Close;
_menu.OpenCentered();
}
public void Update(ProtoId<BarSignPrototype>? sign)
{
if (_prototype.TryIndex(sign, out var signPrototype))
_menu?.UpdateState(signPrototype);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Dispose();
}
}

View File

@@ -0,0 +1,19 @@
<controls:FancyWindow
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc 'barsign-ui-menu'}"
MinSize="280 180"
SetSize="280 180">
<BoxContainer VerticalExpand="True" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10 5 10 10">
<BoxContainer Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center">
<Label Text="{Loc 'barsign-ui-set-label'}" HorizontalAlignment="Center" StyleClasses="LabelSubText" Margin="30 0"/>
<customControls:HSeparator Margin="0 0 0 5"/>
</BoxContainer>
<OptionButton Name="SignOptions" HorizontalAlignment="Center" VerticalAlignment="Center" MinSize="175 60" Margin="0 0 0 20"/>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -0,0 +1,50 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.BarSign;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.BarSign.Ui;
[GenerateTypedNameReferences]
public sealed partial class BarSignMenu : FancyWindow
{
private string? _currentId;
private readonly List<BarSignPrototype> _cachedPrototypes = new();
public event Action<string>? OnSignSelected;
public BarSignMenu(BarSignPrototype? currentSign, List<BarSignPrototype> signs)
{
RobustXamlLoader.Load(this);
_currentId = currentSign?.ID;
_cachedPrototypes.Clear();
_cachedPrototypes = signs;
foreach (var proto in _cachedPrototypes)
{
SignOptions.AddItem(Loc.GetString(proto.Name));
}
SignOptions.OnItemSelected += idx =>
{
OnSignSelected?.Invoke(_cachedPrototypes[idx.Id].ID);
SignOptions.SelectId(idx.Id);
};
if (currentSign != null)
{
var idx = _cachedPrototypes.IndexOf(currentSign);
SignOptions.TrySelectId(idx);
}
}
public void UpdateState(BarSignPrototype newSign)
{
if (_currentId != null && newSign.ID == _currentId)
return;
_currentId = newSign.ID;
var idx = _cachedPrototypes.IndexOf(newSign);
SignOptions.TrySelectId(idx);
}
}

View File

@@ -48,7 +48,7 @@ namespace Content.Client.Clickable
Angle cardinalSnapping = sprite.SnapCardinals ? relativeRotation.GetCardinalDir().ToAngle() : Angle.Zero;
// First we get `localPos`, the clicked location in the sprite-coordinate frame.
var entityXform = Matrix3Helpers.CreateInverseTransform(transform.WorldPosition, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping);
var entityXform = Matrix3Helpers.CreateInverseTransform(spritePos, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping);
var localPos = Vector2.Transform(Vector2.Transform(worldPos, entityXform), invSpriteMatrix);
// Check explicitly defined click-able bounds
@@ -58,8 +58,11 @@ namespace Content.Client.Clickable
// Next check each individual sprite layer using automatically computed click maps.
foreach (var spriteLayer in sprite.AllLayers)
{
if (!spriteLayer.Visible || spriteLayer is not Layer layer)
// TODO: Move this to a system and also use SpriteSystem.IsVisible instead.
if (!spriteLayer.Visible || spriteLayer is not Layer layer || layer.CopyToShaderParameters != null)
{
continue;
}
// Check the layer's texture, if it has one
if (layer.Texture != null)

View File

@@ -20,7 +20,7 @@ public sealed class ZoomCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
Vector2 zoom;
if (args.Length is not (1 or 2))
if (args.Length is not (1 or 2 or 3))
{
shell.WriteLine(Help);
return;
@@ -57,11 +57,18 @@ public sealed class ZoomCommand : LocalizedCommands
}
}
var scalePvs = true;
if (args.Length == 3 && !bool.TryParse(args[2], out scalePvs))
{
shell.WriteError(LocalizationManager.GetString("cmd-parse-failure-bool", ("arg", args[2])));
return;
}
var player = _playerManager.LocalSession?.AttachedEntity;
if (_entityManager.TryGetComponent<ContentEyeComponent>(player, out var content))
{
_entityManager.System<ContentEyeSystem>().RequestZoom(player.Value, zoom, true, content);
_entityManager.System<ContentEyeSystem>().RequestZoom(player.Value, zoom, true, scalePvs, content);
return;
}

View File

@@ -1,5 +1,4 @@
using Content.Client.Verbs;
using Content.Shared.Eye.Blinding;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Content.Shared.Input;
@@ -16,8 +15,6 @@ using Robust.Shared.Utility;
using System.Linq;
using System.Numerics;
using System.Threading;
using Content.Shared.Eye.Blinding.Components;
using Robust.Client;
using static Content.Shared.Interaction.SharedInteractionSystem;
using static Robust.Client.UserInterface.Controls.BoxContainer;
using Content.Shared.Interaction.Events;
@@ -360,10 +357,7 @@ namespace Content.Client.Examine
FormattedMessage message;
// Basically this just predicts that we can't make out the entity if we have poor vision.
var canSeeClearly = !HasComp<BlurryVisionComponent>(playerEnt);
OpenTooltip(playerEnt.Value, entity, centeredOnCursor, false, knowTarget: canSeeClearly);
OpenTooltip(playerEnt.Value, entity, centeredOnCursor, false);
// Always update tooltip info from client first.
// If we get it wrong, server will correct us later anyway.

View File

@@ -48,6 +48,9 @@ namespace Content.Client.Jittering
if(args.Key != _jitterAnimationKey)
return;
if (!args.Finished)
return;
if (TryComp(uid, out AnimationPlayerComponent? animationPlayer)
&& TryComp(uid, out SpriteComponent? sprite))
_animationPlayer.Play(uid, animationPlayer, GetAnimation(jittering, sprite), _jitterAnimationKey);

View File

@@ -217,12 +217,12 @@ public sealed partial class LatheMenu : DefaultWindow
queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal;
var queuedRecipeProto = new EntityPrototypeView();
queuedRecipeBox.AddChild(queuedRecipeProto);
if (_prototypeManager.TryIndex(recipe.Result, out EntityPrototype? entityProto) && entityProto != null)
queuedRecipeProto.SetPrototype(entityProto);
var queuedRecipeLabel = new Label();
queuedRecipeLabel.Text = $"{idx}. {recipe.Name}";
queuedRecipeBox.AddChild(queuedRecipeProto);
queuedRecipeBox.AddChild(queuedRecipeLabel);
QueueList.AddChild(queuedRecipeBox);
idx++;

View File

@@ -116,7 +116,7 @@ namespace Content.Client.Launcher
private void ChangeLoginTip()
{
var tipsDataset = _cfg.GetCVar(CCVars.LoginTipsDataset);
var loginTipsEnabled = _prototype.TryIndex<DatasetPrototype>(tipsDataset, out var tips);
var loginTipsEnabled = _prototype.TryIndex<LocalizedDatasetPrototype>(tipsDataset, out var tips);
LoginTips.Visible = loginTipsEnabled;
if (!loginTipsEnabled)
@@ -131,7 +131,7 @@ namespace Content.Client.Launcher
var randomIndex = _random.Next(tipList.Count);
var tip = tipList[randomIndex];
LoginTip.SetMessage(tip);
LoginTip.SetMessage(Loc.GetString(tip));
LoginTipTitle.Text = Loc.GetString("connecting-window-tip", ("numberTip", randomIndex));
}

View File

@@ -19,6 +19,9 @@ public sealed class LightBehaviorSystem : EntitySystem
private void OnBehaviorAnimationCompleted(EntityUid uid, LightBehaviourComponent component, AnimationCompletedEvent args)
{
if (!args.Finished)
return;
var container = component.Animations.FirstOrDefault(x => x.FullKey == args.Key);
if (container == null)

View File

@@ -69,6 +69,9 @@ public sealed class RotatingLightSystem : SharedRotatingLightSystem
private void OnAnimationComplete(EntityUid uid, RotatingLightComponent comp, AnimationCompletedEvent args)
{
if (!args.Finished)
return;
PlayAnimation(uid, comp);
}

View File

@@ -2,7 +2,6 @@
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Client.Replays.Loading;
using Robust.Shared.Map;
using Robust.Shared.Timing;
@@ -46,13 +45,19 @@ public sealed class MouseRotatorSystem : SharedMouseRotatorSystem
// only raise event if the cardinal direction has changed
if (rotator.Simple4DirMode)
{
var angleDir = angle.GetCardinalDir();
if (angleDir == curRot.GetCardinalDir())
var eyeRot = _eye.CurrentEye.Rotation; // camera rotation
var angleDir = (angle + eyeRot).GetCardinalDir(); // apply GetCardinalDir in the camera frame, not in the world frame
if (angleDir == (curRot + eyeRot).GetCardinalDir())
return;
RaisePredictiveEvent(new RequestMouseRotatorRotationSimpleEvent()
var rotation = angleDir.ToAngle() - eyeRot; // convert back to world frame
if (rotation >= Math.PI) // convert to [-PI, +PI)
rotation -= 2 * Math.PI;
else if (rotation < -Math.PI)
rotation += 2 * Math.PI;
RaisePredictiveEvent(new RequestMouseRotatorRotationEvent
{
Direction = angleDir,
Rotation = rotation
});
return;

View File

@@ -9,7 +9,7 @@ public sealed class ContentEyeSystem : SharedContentEyeSystem
{
[Dependency] private readonly IPlayerManager _player = default!;
public void RequestZoom(EntityUid uid, Vector2 zoom, bool ignoreLimit, ContentEyeComponent? content = null)
public void RequestZoom(EntityUid uid, Vector2 zoom, bool ignoreLimit, bool scalePvs, ContentEyeComponent? content = null)
{
if (!Resolve(uid, ref content, false))
return;
@@ -19,6 +19,14 @@ public sealed class ContentEyeSystem : SharedContentEyeSystem
TargetZoom = zoom,
IgnoreLimit = ignoreLimit,
});
if (scalePvs)
RequestPvsScale(Math.Max(zoom.X, zoom.Y));
}
public void RequestPvsScale(float scale)
{
RaiseNetworkEvent(new RequestPvsScaleEvent(scale));
}
public void RequestToggleFov()

View File

@@ -23,8 +23,8 @@ public sealed class RotationVisualizerSystem : SharedRotationVisualsSystem
if (args.Sprite == null)
return;
// If not defined, defaults to standing.
_appearance.TryGetData<RotationState>(uid, RotationVisuals.RotationState, out var state, args.Component);
if (!_appearance.TryGetData<RotationState>(uid, RotationVisuals.RotationState, out var state, args.Component))
return;
switch (state)
{

View File

@@ -129,14 +129,7 @@ public sealed partial class SensorMonitoringWindow : FancyWindow, IComputerWindo
foreach (var stream in sensor.Streams.Values)
{
var maxValue = stream.Unit switch
{
SensorUnit.PressureKpa => 5000, // 5 MPa
SensorUnit.Ratio => 1,
SensorUnit.PowerW => 1_000_000, // 1 MW
SensorUnit.EnergyJ => 2_000_000, // 2 MJ
_ => 1000
};
var maxValue = stream.Samples.Max(x => x.Value);
// TODO: Better way to do this?
var lastSample = stream.Samples.Last();
@@ -151,7 +144,7 @@ public sealed partial class SensorMonitoringWindow : FancyWindow, IComputerWindo
}
});
Asdf.AddChild(new GraphView(stream.Samples, startTime, curTime, maxValue) { MinHeight = 150 });
Asdf.AddChild(new GraphView(stream.Samples, startTime, curTime, maxValue * 1.1f) { MinHeight = 150 });
Asdf.AddChild(new PanelContainer { StyleClasses = { StyleBase.ClassLowDivider } });
}
}

View File

@@ -0,0 +1,82 @@
using System.Numerics;
using Content.Shared.Shuttles.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Client.Shuttles;
/// <summary>
/// Plays a visualization whenever a shuttle is arriving from FTL.
/// </summary>
public sealed class FtlArrivalOverlay : Overlay
{
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowEntities;
private EntityLookupSystem _lookups;
private SharedMapSystem _maps;
private SharedTransformSystem _transforms;
private SpriteSystem _sprites;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPrototypeManager _protos = default!;
private readonly HashSet<Entity<FtlVisualizerComponent>> _visualizers = new();
private ShaderInstance _shader;
public FtlArrivalOverlay()
{
IoCManager.InjectDependencies(this);
_lookups = _entManager.System<EntityLookupSystem>();
_transforms = _entManager.System<SharedTransformSystem>();
_maps = _entManager.System<SharedMapSystem>();
_sprites = _entManager.System<SpriteSystem>();
_shader = _protos.Index<ShaderPrototype>("unshaded").Instance();
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
_visualizers.Clear();
_lookups.GetEntitiesOnMap(args.MapId, _visualizers);
return _visualizers.Count > 0;
}
protected override void Draw(in OverlayDrawArgs args)
{
args.WorldHandle.UseShader(_shader);
foreach (var (uid, comp) in _visualizers)
{
var grid = comp.Grid;
if (!_entManager.TryGetComponent(grid, out MapGridComponent? mapGrid))
continue;
var texture = _sprites.GetFrame(comp.Sprite, TimeSpan.FromSeconds(comp.Elapsed), loop: false);
comp.Elapsed += (float) _timing.FrameTime.TotalSeconds;
// Need to manually transform the viewport in terms of the visualizer entity as the grid isn't in position.
var (_, _, worldMatrix, invMatrix) = _transforms.GetWorldPositionRotationMatrixWithInv(uid);
args.WorldHandle.SetTransform(worldMatrix);
var localAABB = invMatrix.TransformBox(args.WorldBounds);
var tilesEnumerator = _maps.GetLocalTilesEnumerator(grid, mapGrid, localAABB);
while (tilesEnumerator.MoveNext(out var tile))
{
var bounds = _lookups.GetLocalBounds(tile, mapGrid.TileSize);
args.WorldHandle.DrawTextureRect(texture, bounds);
}
}
args.WorldHandle.UseShader(null);
args.WorldHandle.SetTransform(Matrix3x2.Identity);
}
}

View File

@@ -38,9 +38,8 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
private bool _enableShuttlePosition;
private EmergencyShuttleOverlay? _overlay;
public override void Initialize()
private void InitializeEmergency()
{
base.Initialize();
SubscribeNetworkEvent<EmergencyShuttlePositionMessage>(OnShuttlePosMessage);
}

View File

@@ -0,0 +1,21 @@
using Robust.Client.Graphics;
namespace Content.Client.Shuttles.Systems;
public sealed partial class ShuttleSystem
{
[Dependency] private readonly IOverlayManager _overlays = default!;
public override void Initialize()
{
base.Initialize();
InitializeEmergency();
_overlays.AddOverlay(new FtlArrivalOverlay());
}
public override void Shutdown()
{
base.Shutdown();
_overlays.RemoveOverlay<FtlArrivalOverlay>();
}
}

View File

@@ -67,11 +67,18 @@ public class RadialContainer : LayoutContainer
{
}
protected override void Draw(DrawingHandleScreen handle)
{
const float baseRadius = 100f;
const float radiusIncrement = 5f;
var children = ReserveSpaceForHiddenChildren ? Children : Children.Where(x => x.Visible);
var childCount = children.Count();
// Add padding from the center at higher child counts so they don't overlap.
Radius = baseRadius + (childCount * radiusIncrement);
// Determine the size of the arc, accounting for clockwise and anti-clockwise arrangements
var arc = AngularRange.Y - AngularRange.X;

View File

@@ -18,7 +18,7 @@ public sealed class ActionsAddedTest
[Test]
public async Task TestCombatActionsAdded()
{
await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false});
await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false });
var server = pair.Server;
var client = pair.Client;
var sEntMan = server.ResolveDependency<IEntityManager>();

View File

@@ -5,7 +5,7 @@ using Robust.Shared.GameObjects;
namespace Content.IntegrationTests.Tests.Body;
[TestFixture]
public sealed class GibTest
public sealed class GibTest
{
[Test]
public async Task TestGib()

View File

@@ -5,7 +5,6 @@ using Content.Shared.Body.Part;
using Content.Shared.Rotation;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Content.IntegrationTests.Tests.Body
{
@@ -40,13 +39,14 @@ namespace Content.IntegrationTests.Tests.Body
var appearanceSystem = entityManager.System<SharedAppearanceSystem>();
var xformSystem = entityManager.System<SharedTransformSystem>();
var map = await pair.CreateTestMap();
await server.WaitAssertion(() =>
{
var mapId = mapManager.CreateMap();
BodyComponent body = null;
human = entityManager.SpawnEntity("HumanBodyAndAppearanceDummy",
new MapCoordinates(Vector2.Zero, mapId));
new MapCoordinates(Vector2.Zero, map.MapId));
Assert.Multiple(() =>
{
@@ -61,7 +61,7 @@ namespace Content.IntegrationTests.Tests.Body
foreach (var leg in legs)
{
xformSystem.DetachParentToNull(leg.Id, entityManager.GetComponent<TransformComponent>(leg.Id));
xformSystem.DetachEntity(leg.Id, entityManager.GetComponent<TransformComponent>(leg.Id));
}
});

View File

@@ -60,8 +60,8 @@ namespace Content.IntegrationTests.Tests.Body
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var mapLoader = entityManager.System<MapLoaderSystem>();
var mapSys = entityManager.System<SharedMapSystem>();
MapId mapId;
EntityUid? grid = null;
BodyComponent body = default;
RespiratorComponent resp = default;
@@ -73,7 +73,7 @@ namespace Content.IntegrationTests.Tests.Body
await server.WaitPost(() =>
{
mapId = mapManager.CreateMap();
mapSys.CreateMap(out var mapId);
Assert.That(mapLoader.TryLoad(mapId, testMapName, out var roots));
var query = entityManager.GetEntityQuery<MapGridComponent>();
@@ -142,8 +142,8 @@ namespace Content.IntegrationTests.Tests.Body
var entityManager = server.ResolveDependency<IEntityManager>();
var cfg = server.ResolveDependency<IConfigurationManager>();
var mapLoader = entityManager.System<MapLoaderSystem>();
var mapSys = entityManager.System<SharedMapSystem>();
MapId mapId;
EntityUid? grid = null;
RespiratorComponent respirator = null;
EntityUid human = default;
@@ -152,7 +152,7 @@ namespace Content.IntegrationTests.Tests.Body
await server.WaitPost(() =>
{
mapId = mapManager.CreateMap();
mapSys.CreateMap(out var mapId);
Assert.That(mapLoader.TryLoad(mapId, testMapName, out var ents), Is.True);
var query = entityManager.GetEntityQuery<MapGridComponent>();

View File

@@ -33,10 +33,11 @@ public sealed class SaveLoadReparentTest
var mapLoader = entities.System<MapLoaderSystem>();
var bodySystem = entities.System<SharedBodySystem>();
var containerSystem = entities.System<SharedContainerSystem>();
var mapSys = entities.System<SharedMapSystem>();
await server.WaitAssertion(() =>
{
var mapId = maps.CreateMap();
mapSys.CreateMap(out var mapId);
maps.CreateGrid(mapId);
var human = entities.SpawnEntity("HumanBodyDummy", new MapCoordinates(0, 0, mapId));
@@ -115,7 +116,7 @@ public sealed class SaveLoadReparentTest
mapLoader.SaveMap(mapId, mapPath);
maps.DeleteMap(mapId);
mapId = maps.CreateMap();
mapSys.CreateMap(out mapId);
Assert.That(mapLoader.TryLoad(mapId, mapPath, out _), Is.True);
var query = EnumerateQueryEnumerator(

View File

@@ -38,13 +38,13 @@ public sealed class BuckleDragTest : InteractionTest
await RunTicks(5);
Assert.That(buckle.Buckled, Is.True);
Assert.That(buckle.BuckledTo, Is.EqualTo(STarget));
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[]{sUrist}));
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[] { sUrist }));
Assert.That(puller.Pulling, Is.Null);
Assert.That(pullable.Puller, Is.Null);
Assert.That(pullable.BeingPulled, Is.False);
// Start pulling, and thus unbuckle them
await PressKey(ContentKeyFunctions.TryPullObject, cursorEntity:urist);
await PressKey(ContentKeyFunctions.TryPullObject, cursorEntity: urist);
await RunTicks(5);
Assert.That(buckle.Buckled, Is.False);
Assert.That(buckle.BuckledTo, Is.Null);

View File

@@ -19,11 +19,11 @@ namespace Content.IntegrationTests.Tests;
[TestFixture]
public sealed class CargoTest
{
public static HashSet<ProtoId<CargoProductPrototype>> Ignored = new ()
{
private static readonly HashSet<ProtoId<CargoProductPrototype>> Ignored =
[
// This is ignored because it is explicitly intended to be able to sell for more than it costs.
new("FunCrateGambling")
};
];
[Test]
public async Task NoCargoOrderArbitrage()

View File

@@ -9,10 +9,10 @@ namespace Content.IntegrationTests.Tests.Chemistry
{
public sealed class FixedPoint2SerializationTest : SerializationTest
{
protected override Assembly[] Assemblies => new[]
{
protected override Assembly[] Assemblies =>
[
typeof(FixedPoint2SerializationTest).Assembly
};
];
[Test]
public void DeserializeNullTest()
@@ -53,6 +53,6 @@ namespace Content.IntegrationTests.Tests.Chemistry
[DataDefinition]
public sealed partial class FixedPoint2TestDefinition
{
[DataField("unit")] public FixedPoint2? Unit { get; set; } = FixedPoint2.New(5);
[DataField] public FixedPoint2? Unit { get; set; } = FixedPoint2.New(5);
}
}

View File

@@ -1,5 +1,5 @@
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
@@ -76,7 +76,7 @@ public sealed class SolutionRoundingTest
await server.WaitPost(() =>
{
var system = server.System<SolutionContainerSystem>();
var system = server.System<SharedSolutionContainerSystem>();
var beaker = server.EntMan.SpawnEntity("SolutionRoundingTestContainer", testMap.GridCoords);
system.TryGetSolution(beaker, "beaker", out var newSolutionEnt, out var newSolution);

View File

@@ -1,5 +1,5 @@
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.FixedPoint;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
@@ -11,7 +11,7 @@ namespace Content.IntegrationTests.Tests.Chemistry;
// To ensure volume(A) + volume(B) = volume(A+B)
// reactions can change this assumption
[TestFixture]
[TestOf(typeof(SolutionContainerSystem))]
[TestOf(typeof(SharedSolutionContainerSystem))]
public sealed class SolutionSystemTests
{
[TestPrototypes]
@@ -51,7 +51,7 @@ public sealed class SolutionSystemTests
var entityManager = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var containerSystem = entityManager.System<SolutionContainerSystem>();
var containerSystem = entityManager.System<SharedSolutionContainerSystem>();
var testMap = await pair.CreateTestMap();
var coordinates = testMap.GridCoords;
@@ -97,7 +97,7 @@ public sealed class SolutionSystemTests
var entityManager = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var containerSystem = entityManager.System<SolutionContainerSystem>();
var containerSystem = entityManager.System<SharedSolutionContainerSystem>();
var coordinates = testMap.GridCoords;
EntityUid beaker;
@@ -141,7 +141,7 @@ public sealed class SolutionSystemTests
var entityManager = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var testMap = await pair.CreateTestMap();
var containerSystem = entityManager.System<SolutionContainerSystem>();
var containerSystem = entityManager.System<SharedSolutionContainerSystem>();
var coordinates = testMap.GridCoords;
EntityUid beaker;
@@ -194,7 +194,7 @@ public sealed class SolutionSystemTests
var entityManager = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var containerSystem = entityManager.System<SolutionContainerSystem>();
var containerSystem = entityManager.System<SharedSolutionContainerSystem>();
var testMap = await pair.CreateTestMap();
var coordinates = testMap.GridCoords;

View File

@@ -1,4 +1,3 @@
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Components;
using Robust.Shared.GameObjects;
@@ -6,6 +5,7 @@ using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using System.Linq;
using Content.Shared.Chemistry.EntitySystems;
namespace Content.IntegrationTests.Tests.Chemistry
{
@@ -34,7 +34,7 @@ namespace Content.IntegrationTests.Tests.Chemistry
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
var testMap = await pair.CreateTestMap();
var coordinates = testMap.GridCoords;
var solutionContainerSystem = entityManager.System<SolutionContainerSystem>();
var solutionContainerSystem = entityManager.System<SharedSolutionContainerSystem>();
foreach (var reactionPrototype in prototypeManager.EnumeratePrototypes<ReactionPrototype>())
{

View File

@@ -28,7 +28,7 @@ namespace Content.IntegrationTests.Tests.Commands
Assert.That(netMan.IsConnected);
Assert.That(sPlayerManager.Sessions.Count(), Is.EqualTo(1));
Assert.That(sPlayerManager.Sessions, Has.Length.EqualTo(1));
// No bans on record
Assert.Multiple(async () =>
{
@@ -50,7 +50,7 @@ namespace Content.IntegrationTests.Tests.Commands
var banReason = "test";
Assert.That(sPlayerManager.Sessions.Count(), Is.EqualTo(1));
Assert.That(sPlayerManager.Sessions, Has.Length.EqualTo(1));
// Ban the client for 24 hours
await server.WaitPost(() => sConsole.ExecuteCommand($"ban {clientSession.Name} {banReason} 1440"));
@@ -63,7 +63,7 @@ namespace Content.IntegrationTests.Tests.Commands
});
await pair.RunTicksSync(5);
Assert.That(sPlayerManager.Sessions.Count(), Is.EqualTo(0));
Assert.That(sPlayerManager.Sessions, Has.Length.EqualTo(0));
Assert.That(!netMan.IsConnected);
// Try to pardon a ban that does not exist
@@ -143,11 +143,11 @@ namespace Content.IntegrationTests.Tests.Commands
});
// Reconnect client. Slightly faster than dirtying the pair.
Assert.That(sPlayerManager.Sessions.Count(), Is.EqualTo(0));
Assert.That(sPlayerManager.Sessions, Is.Empty);
client.SetConnectTarget(server);
await client.WaitPost(() => netMan.ClientConnect(null!, 0, null!));
await pair.RunTicksSync(5);
Assert.That(sPlayerManager.Sessions.Count(), Is.EqualTo(1));
Assert.That(sPlayerManager.Sessions, Has.Length.EqualTo(1));
await pair.CleanReturnAsync();
}

View File

@@ -37,9 +37,9 @@ namespace Content.IntegrationTests.Tests.Commands
var server = pair.Server;
var entManager = server.ResolveDependency<IEntityManager>();
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
var mobStateSystem = entManager.EntitySysManager.GetEntitySystem<MobStateSystem>();
var damSystem = entManager.EntitySysManager.GetEntitySystem<DamageableSystem>();
var rejuvenateSystem = entManager.EntitySysManager.GetEntitySystem<RejuvenateSystem>();
var mobStateSystem = entManager.System<MobStateSystem>();
var damSystem = entManager.System<DamageableSystem>();
var rejuvenateSystem = entManager.System<RejuvenateSystem>();
await server.WaitAssertion(() =>
{

View File

@@ -26,7 +26,7 @@ namespace Content.IntegrationTests.Tests.Commands
var configManager = server.ResolveDependency<IConfigurationManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTicker = entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
var gameTicker = entityManager.System<GameTicker>();
await pair.RunTicksSync(5);

View File

@@ -43,11 +43,11 @@ namespace Content.IntegrationTests.Tests
EntityUid dummy = default;
var mapManager = server.ResolveDependency<IMapManager>();
var mapId = mapManager.CreateMap();
var map = await pair.CreateTestMap();
await server.WaitPost(() =>
{
var pos = new MapCoordinates(Vector2.Zero, mapId);
var pos = new MapCoordinates(Vector2.Zero, map.MapId);
var entStorage = serverEntManager.EntitySysManager.GetEntitySystem<EntityStorageSystem>();
var container = serverEntManager.SpawnEntity("ContainerOcclusionA", pos);
dummy = serverEntManager.SpawnEntity("ContainerOcclusionDummy", pos);
@@ -85,11 +85,12 @@ namespace Content.IntegrationTests.Tests
EntityUid dummy = default;
var mapManager = server.ResolveDependency<IMapManager>();
var mapId = mapManager.CreateMap();
var map = await pair.CreateTestMap();
await server.WaitPost(() =>
{
var pos = new MapCoordinates(Vector2.Zero, mapId);
var pos = new MapCoordinates(Vector2.Zero, map.MapId);
var entStorage = serverEntManager.EntitySysManager.GetEntitySystem<EntityStorageSystem>();
var container = serverEntManager.SpawnEntity("ContainerOcclusionB", pos);
dummy = serverEntManager.SpawnEntity("ContainerOcclusionDummy", pos);
@@ -127,11 +128,12 @@ namespace Content.IntegrationTests.Tests
EntityUid dummy = default;
var mapManager = server.ResolveDependency<IMapManager>();
var mapId = mapManager.CreateMap();
var map = await pair.CreateTestMap();
await server.WaitPost(() =>
{
var pos = new MapCoordinates(Vector2.Zero, mapId);
var pos = new MapCoordinates(Vector2.Zero, map.MapId);
var entStorage = serverEntManager.EntitySysManager.GetEntitySystem<EntityStorageSystem>();
var containerA = serverEntManager.SpawnEntity("ContainerOcclusionA", pos);
var containerB = serverEntManager.SpawnEntity("ContainerOcclusionB", pos);

View File

@@ -14,39 +14,39 @@ public sealed class DamageSpecifierTest
// Test basic math operations.
// I've already nearly broken these once. When editing the operators.
DamageSpecifier input1 = new() { DamageDict = _input1 };
DamageSpecifier input2 = new() { DamageDict = _input2 };
DamageSpecifier output1 = new() { DamageDict = _output1 };
DamageSpecifier output2 = new() { DamageDict = _output2 };
DamageSpecifier output3 = new() { DamageDict = _output3 };
DamageSpecifier output4 = new() { DamageDict = _output4 };
DamageSpecifier output5 = new() { DamageDict = _output5 };
DamageSpecifier input1 = new() { DamageDict = Input1 };
DamageSpecifier input2 = new() { DamageDict = Input2 };
DamageSpecifier output1 = new() { DamageDict = Output1 };
DamageSpecifier output2 = new() { DamageDict = Output2 };
DamageSpecifier output3 = new() { DamageDict = Output3 };
DamageSpecifier output4 = new() { DamageDict = Output4 };
DamageSpecifier output5 = new() { DamageDict = Output5 };
Assert.Multiple(() =>
{
Assert.That((-input1).Equals(output1));
Assert.That((input1 / 2).Equals(output2));
Assert.That((input1 * 2).Equals(output3));
Assert.That(-input1, Is.EqualTo(output1));
Assert.That(input1 / 2, Is.EqualTo(output2));
Assert.That(input1 * 2, Is.EqualTo(output3));
});
var difference = (input1 - input2);
Assert.That(difference.Equals(output4));
var difference = input1 - input2;
Assert.That(difference, Is.EqualTo(output4));
var difference2 = (-input2) + input1;
Assert.That(difference.Equals(difference2));
var difference2 = -input2 + input1;
Assert.That(difference, Is.EqualTo(difference2));
difference.Clamp(-0.25f, 0.25f);
Assert.That(difference.Equals(output5));
Assert.That(difference, Is.EqualTo(output5));
}
static Dictionary<string, FixedPoint2> _input1 = new()
private static readonly Dictionary<string, FixedPoint2> Input1 = new()
{
{ "A", 1.5f },
{ "B", 2 },
{ "C", 3 }
};
static Dictionary<string, FixedPoint2> _input2 = new()
private static readonly Dictionary<string, FixedPoint2> Input2 = new()
{
{ "A", 1 },
{ "B", 2 },
@@ -54,28 +54,28 @@ public sealed class DamageSpecifierTest
{ "D", 0.05f }
};
static Dictionary<string, FixedPoint2> _output1 = new()
private static readonly Dictionary<string, FixedPoint2> Output1 = new()
{
{ "A", -1.5f },
{ "B", -2 },
{ "C", -3 }
};
static Dictionary<string, FixedPoint2> _output2 = new()
private static readonly Dictionary<string, FixedPoint2> Output2 = new()
{
{ "A", 0.75f },
{ "B", 1 },
{ "C", 1.5 }
};
static Dictionary<string, FixedPoint2> _output3 = new()
private static readonly Dictionary<string, FixedPoint2> Output3 = new()
{
{ "A", 3f },
{ "B", 4 },
{ "C", 6 }
};
static Dictionary<string, FixedPoint2> _output4 = new()
private static readonly Dictionary<string, FixedPoint2> Output4 = new()
{
{ "A", 0.5f },
{ "B", 0 },
@@ -83,7 +83,7 @@ public sealed class DamageSpecifierTest
{ "D", -0.05f }
};
static Dictionary<string, FixedPoint2> _output5 = new()
private static readonly Dictionary<string, FixedPoint2> Output5 = new()
{
{ "A", 0.25f },
{ "B", 0 },

View File

@@ -107,10 +107,11 @@ namespace Content.IntegrationTests.Tests.Damageable
FixedPoint2 typeDamage;
var map = await pair.CreateTestMap();
await server.WaitPost(() =>
{
var map = sMapManager.CreateMap();
var coordinates = new MapCoordinates(0, 0, map);
var coordinates = map.MapCoords;
sDamageableEntity = sEntityManager.SpawnEntity("TestDamageableEntityId", coordinates);
sDamageableComponent = sEntityManager.GetComponent<DamageableComponent>(sDamageableEntity);

View File

@@ -123,24 +123,24 @@ namespace Content.IntegrationTests.Tests.Doors
var xformSystem = entityManager.System<SharedTransformSystem>();
PhysicsComponent physBody = null;
EntityUid AirlockPhysicsDummy = default;
EntityUid airlockPhysicsDummy = default;
EntityUid airlock = default;
DoorComponent doorComponent = null;
var AirlockPhysicsDummyStartingX = -1;
var airlockPhysicsDummyStartingX = -1;
var map = await pair.CreateTestMap();
await server.WaitAssertion(() =>
{
var mapId = mapManager.CreateMap();
var humanCoordinates = new MapCoordinates(new Vector2(airlockPhysicsDummyStartingX, 0), map.MapId);
airlockPhysicsDummy = entityManager.SpawnEntity("AirlockPhysicsDummy", humanCoordinates);
var humanCoordinates = new MapCoordinates(new Vector2(AirlockPhysicsDummyStartingX, 0), mapId);
AirlockPhysicsDummy = entityManager.SpawnEntity("AirlockPhysicsDummy", humanCoordinates);
airlock = entityManager.SpawnEntity("AirlockDummy", new MapCoordinates(new Vector2(0, 0), mapId));
airlock = entityManager.SpawnEntity("AirlockDummy", new MapCoordinates(new Vector2(0, 0), map.MapId));
Assert.Multiple(() =>
{
Assert.That(entityManager.TryGetComponent(AirlockPhysicsDummy, out physBody), Is.True);
Assert.That(entityManager.TryGetComponent(airlockPhysicsDummy, out physBody), Is.True);
Assert.That(entityManager.TryGetComponent(airlock, out doorComponent), Is.True);
});
Assert.That(doorComponent.State, Is.EqualTo(DoorState.Closed));
@@ -152,7 +152,7 @@ namespace Content.IntegrationTests.Tests.Doors
await server.WaitAssertion(() => Assert.That(physBody, Is.Not.EqualTo(null)));
await server.WaitPost(() =>
{
physicsSystem.SetLinearVelocity(AirlockPhysicsDummy, new Vector2(0.5f, 0f), body: physBody);
physicsSystem.SetLinearVelocity(airlockPhysicsDummy, new Vector2(0.5f, 0f), body: physBody);
});
for (var i = 0; i < 240; i += 10)
@@ -176,7 +176,7 @@ namespace Content.IntegrationTests.Tests.Doors
// Blocked by the airlock
await server.WaitAssertion(() =>
{
Assert.That(Math.Abs(xformSystem.GetWorldPosition(AirlockPhysicsDummy).X - 1), Is.GreaterThan(0.01f));
Assert.That(Math.Abs(xformSystem.GetWorldPosition(airlockPhysicsDummy).X - 1), Is.GreaterThan(0.01f));
});
await pair.CleanReturnAsync();
}

View File

@@ -21,7 +21,7 @@ namespace Content.IntegrationTests.Tests
{
foreach (var proto in prototypeManager.EnumeratePrototypes<EntityPrototype>())
{
if (proto.NoSpawn || proto.Abstract || pair.IsTestPrototype(proto) || !proto.Components.ContainsKey("Sprite"))
if (proto.HideSpawnMenu || proto.Abstract || pair.IsTestPrototype(proto) || !proto.Components.ContainsKey("Sprite"))
continue;
Assert.DoesNotThrow(() =>

View File

@@ -1,15 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Content.Server.Humanoid.Components;
using Content.Shared.Coordinates;
using Content.Shared.Prototypes;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
@@ -47,7 +43,7 @@ namespace Content.IntegrationTests.Tests
foreach (var protoId in protoIds)
{
var mapId = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// TODO: Fix this better in engine.
mapSystem.SetTile(grid.Owner, grid.Comp, Vector2i.Zero, new Tile(1));
@@ -155,6 +151,7 @@ namespace Content.IntegrationTests.Tests
var prototypeMan = server.ResolveDependency<IPrototypeManager>();
var mapManager = server.ResolveDependency<IMapManager>();
var sEntMan = server.ResolveDependency<IEntityManager>();
var mapSys = server.System<SharedMapSystem>();
Assert.That(cfg.GetCVar(CVars.NetPVS), Is.False);
@@ -170,7 +167,7 @@ namespace Content.IntegrationTests.Tests
{
foreach (var protoId in protoIds)
{
var mapId = mapManager.CreateMap();
mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
var ent = sEntMan.SpawnEntity(protoId, new EntityCoordinates(grid.Owner, 0.5f, 0.5f));
foreach (var (_, component) in sEntMan.GetNetComponents(ent))
@@ -227,6 +224,7 @@ namespace Content.IntegrationTests.Tests
var settings = new PoolSettings { Connected = true, Dirty = true };
await using var pair = await PoolManager.GetServerClient(settings);
var mapManager = pair.Server.ResolveDependency<IMapManager>();
var mapSys = pair.Server.System<SharedMapSystem>();
var server = pair.Server;
var client = pair.Client;
@@ -256,7 +254,7 @@ namespace Content.IntegrationTests.Tests
await server.WaitPost(() =>
{
mapId = mapManager.CreateMap();
mapSys.CreateMap(out mapId);
});
var coords = new MapCoordinates(Vector2.Zero, mapId);

View File

@@ -16,14 +16,15 @@ namespace Content.IntegrationTests.Tests.Fluids;
[TestOf(typeof(SpreaderSystem))]
public sealed class FluidSpill
{
private static PuddleComponent? GetPuddle(IEntityManager entityManager, MapGridComponent mapGrid, Vector2i pos)
private static PuddleComponent? GetPuddle(IEntityManager entityManager, Entity<MapGridComponent> mapGrid, Vector2i pos)
{
return GetPuddleEntity(entityManager, mapGrid, pos)?.Comp;
}
private static Entity<PuddleComponent>? GetPuddleEntity(IEntityManager entityManager, MapGridComponent mapGrid, Vector2i pos)
private static Entity<PuddleComponent>? GetPuddleEntity(IEntityManager entityManager, Entity<MapGridComponent> mapGrid, Vector2i pos)
{
foreach (var uid in mapGrid.GetAnchoredEntities(pos))
var mapSys = entityManager.System<SharedMapSystem>();
foreach (var uid in mapSys.GetAnchoredEntities(mapGrid, mapGrid.Comp, pos))
{
if (entityManager.TryGetComponent(uid, out PuddleComponent? puddleComponent))
return (uid, puddleComponent);
@@ -39,9 +40,9 @@ public sealed class FluidSpill
var server = pair.Server;
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var puddleSystem = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<PuddleSystem>();
var puddleSystem = server.System<PuddleSystem>();
var mapSystem = server.System<SharedMapSystem>();
var gameTiming = server.ResolveDependency<IGameTiming>();
MapId mapId;
EntityUid gridId = default;
/*
@@ -52,7 +53,7 @@ public sealed class FluidSpill
*/
await server.WaitPost(() =>
{
mapId = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
gridId = grid.Owner;
@@ -60,12 +61,12 @@ public sealed class FluidSpill
{
for (var y = 0; y < 3; y++)
{
grid.Comp.SetTile(new Vector2i(x, y), new Tile(1));
mapSystem.SetTile(grid, new Vector2i(x, y), new Tile(1));
}
}
entityManager.SpawnEntity("WallReinforced", grid.Comp.GridTileToLocal(new Vector2i(0, 1)));
entityManager.SpawnEntity("WallReinforced", grid.Comp.GridTileToLocal(new Vector2i(1, 0)));
entityManager.SpawnEntity("WallReinforced", mapSystem.GridTileToLocal(grid, grid.Comp, new Vector2i(0, 1)));
entityManager.SpawnEntity("WallReinforced", mapSystem.GridTileToLocal(grid, grid.Comp, new Vector2i(1, 0)));
});
@@ -74,10 +75,10 @@ public sealed class FluidSpill
{
var grid = entityManager.GetComponent<MapGridComponent>(gridId);
var solution = new Solution("Blood", FixedPoint2.New(100));
var tileRef = grid.GetTileRef(puddleOrigin);
var tileRef = mapSystem.GetTileRef(gridId, grid, puddleOrigin);
#pragma warning disable NUnit2045 // Interdependent tests
Assert.That(puddleSystem.TrySpillAt(tileRef, solution, out _), Is.True);
Assert.That(GetPuddle(entityManager, grid, puddleOrigin), Is.Not.Null);
Assert.That(GetPuddle(entityManager, (gridId, grid), puddleOrigin), Is.Not.Null);
#pragma warning restore NUnit2045
});
@@ -87,7 +88,7 @@ public sealed class FluidSpill
await server.WaitAssertion(() =>
{
var grid = entityManager.GetComponent<MapGridComponent>(gridId);
var puddle = GetPuddleEntity(entityManager, grid, puddleOrigin);
var puddle = GetPuddleEntity(entityManager, (gridId, grid), puddleOrigin);
#pragma warning disable NUnit2045 // Interdependent tests
Assert.That(puddle, Is.Not.Null);
@@ -104,7 +105,7 @@ public sealed class FluidSpill
}
var newPos = new Vector2i(x, y);
var sidePuddle = GetPuddle(entityManager, grid, newPos);
var sidePuddle = GetPuddle(entityManager, (gridId, grid), newPos);
Assert.That(sidePuddle, Is.Null);
}
}

View File

@@ -5,7 +5,6 @@ using Content.Shared.FixedPoint;
using Content.Shared.Fluids.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
namespace Content.IntegrationTests.Tests.Fluids
{
@@ -21,8 +20,7 @@ namespace Content.IntegrationTests.Tests.Fluids
var testMap = await pair.CreateTestMap();
var entitySystemManager = server.ResolveDependency<IEntitySystemManager>();
var spillSystem = entitySystemManager.GetEntitySystem<PuddleSystem>();
var spillSystem = server.System<PuddleSystem>();
await server.WaitAssertion(() =>
{
@@ -46,17 +44,19 @@ namespace Content.IntegrationTests.Tests.Fluids
var server = pair.Server;
var testMap = await pair.CreateTestMap();
var grid = testMap.Grid.Comp;
var grid = testMap.Grid;
var entitySystemManager = server.ResolveDependency<IEntitySystemManager>();
var spillSystem = entitySystemManager.GetEntitySystem<PuddleSystem>();
var spillSystem = server.System<PuddleSystem>();
var mapSystem = server.System<SharedMapSystem>();
// Remove all tiles
await server.WaitPost(() =>
{
foreach (var tile in grid.GetAllTiles())
var tiles = mapSystem.GetAllTiles(grid.Owner, grid.Comp);
foreach (var tile in tiles)
{
grid.SetTile(tile.GridIndices, Tile.Empty);
mapSystem.SetTile(grid, tile.GridIndices, Tile.Empty);
}
});

View File

@@ -22,6 +22,7 @@ public sealed class FollowerSystemTest
var mapMan = server.ResolveDependency<IMapManager>();
var sysMan = server.ResolveDependency<IEntitySystemManager>();
var logMan = server.ResolveDependency<ILogManager>();
var mapSys = server.System<SharedMapSystem>();
var logger = logMan.RootSawmill;
await server.WaitPost(() =>
@@ -29,7 +30,7 @@ public sealed class FollowerSystemTest
var followerSystem = sysMan.GetEntitySystem<FollowerSystem>();
// Create a map to spawn the observers on.
var map = mapMan.CreateMap();
mapSys.CreateMap(out var map);
// Spawn an observer to be followed.
var followed = entMan.SpawnEntity(GameTicker.ObserverPrototypeName, new MapCoordinates(0, 0, map));
@@ -41,7 +42,7 @@ public sealed class FollowerSystemTest
followerSystem.StartFollowingEntity(follower, followed);
entMan.DeleteEntity(mapMan.GetMapEntityId(map));
entMan.DeleteEntity(mapSys.GetMap(map));
});
await pair.CleanReturnAsync();
}

View File

@@ -1,5 +1,4 @@
#nullable enable
using System.Numerics;
using Content.Server.Cuffs;
using Content.Shared.Body.Components;
using Content.Shared.Cuffs.Components;
@@ -7,7 +6,6 @@ using Content.Shared.Hands.Components;
using Robust.Server.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking
{
@@ -52,10 +50,11 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking
var mapManager = server.ResolveDependency<IMapManager>();
var host = server.ResolveDependency<IServerConsoleHost>();
var map = await pair.CreateTestMap();
await server.WaitAssertion(() =>
{
var mapId = mapManager.CreateMap();
var coordinates = new MapCoordinates(Vector2.Zero, mapId);
var coordinates = map.MapCoords;
var cuffableSys = entityManager.System<CuffableSystem>();
var xformSys = entityManager.System<SharedTransformSystem>();

View File

@@ -47,7 +47,7 @@ public sealed class AntagPreferenceTest
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 sessions = new List<ICommonSession> { pair.Player! };
var pool = sys.GetPlayerPool(rule, sessions, def);
Assert.That(pool.Count, Is.EqualTo(0));

View File

@@ -110,7 +110,7 @@ public sealed class FailAndStartPresetTest
player = pair.Player!.AttachedEntity!.Value;
Assert.That(entMan.EntityExists(player));
ticker.SetGamePreset((GamePresetPrototype?)null);
ticker.SetGamePreset((GamePresetPrototype?) null);
server.CfgMan.SetCVar(CCVars.GridFill, false);
server.CfgMan.SetCVar(CCVars.GameLobbyFallbackEnabled, true);
server.CfgMan.SetCVar(CCVars.GameLobbyDefaultPreset, "secret");

View File

@@ -7,6 +7,7 @@ using Content.Server.GameTicking.Rules.Components;
using Content.Server.Mind;
using Content.Server.Pinpointer;
using Content.Server.Roles;
using Content.Server.RoundEnd;
using Content.Server.Shuttles.Components;
using Content.Server.Station.Components;
using Content.Shared.CCVar;
@@ -49,6 +50,7 @@ public sealed class NukeOpsTest
var roleSys = server.System<RoleSystem>();
var invSys = server.System<InventorySystem>();
var factionSys = server.System<NpcFactionSystem>();
var roundEndSys = server.System<RoundEndSystem>();
server.CfgMan.SetCVar(CCVars.GridFill, true);
@@ -63,11 +65,11 @@ public sealed class NukeOpsTest
// Opt into the nukies role.
await pair.SetAntagPreference("NukeopsCommander", true);
await pair.SetAntagPreference( "NukeopsMedic", true, dummies[1].UserId);
await pair.SetAntagPreference("NukeopsMedic", true, dummies[1].UserId);
// Initially, the players have no attached entities
Assert.That(pair.Player?.AttachedEntity, Is.Null);
Assert.That(dummies.All(x => x.AttachedEntity == null));
Assert.That(dummies.All(x => x.AttachedEntity == null));
// There are no grids or maps
Assert.That(entMan.Count<MapComponent>(), Is.Zero);
@@ -150,7 +152,8 @@ public sealed class NukeOpsTest
}
// The game rule exists, and all the stations/shuttles/maps are properly initialized
var rule = entMan.AllComponents<NukeopsRuleComponent>().Single().Component;
var rule = entMan.AllComponents<NukeopsRuleComponent>().Single();
var ruleComp = rule.Component;
var gridsRule = entMan.AllComponents<RuleGridsComponent>().Single().Component;
foreach (var grid in gridsRule.MapGrids)
{
@@ -158,12 +161,14 @@ public sealed class NukeOpsTest
Assert.That(entMan.HasComponent<MapGridComponent>(grid));
Assert.That(entMan.HasComponent<StationMemberComponent>(grid));
}
Assert.That(entMan.EntityExists(rule.TargetStation));
Assert.That(entMan.EntityExists(ruleComp.TargetStation));
Assert.That(entMan.HasComponent<StationDataComponent>(rule.TargetStation));
Assert.That(entMan.HasComponent<StationDataComponent>(ruleComp.TargetStation));
var nukieShuttlEnt = entMan.AllComponents<NukeOpsShuttleComponent>().FirstOrDefault().Uid;
var nukieShuttle = entMan.AllComponents<NukeOpsShuttleComponent>().Single();
var nukieShuttlEnt = nukieShuttle.Uid;
Assert.That(entMan.EntityExists(nukieShuttlEnt));
Assert.That(nukieShuttle.Component.AssociatedRule, Is.EqualTo(rule.Uid));
EntityUid? nukieStationEnt = null;
foreach (var grid in gridsRule.MapGrids)
@@ -179,12 +184,12 @@ public sealed class NukeOpsTest
var nukieStation = entMan.GetComponent<StationMemberComponent>(nukieStationEnt!.Value);
Assert.That(entMan.EntityExists(nukieStation.Station));
Assert.That(nukieStation.Station, Is.Not.EqualTo(rule.TargetStation));
Assert.That(nukieStation.Station, Is.Not.EqualTo(ruleComp.TargetStation));
Assert.That(server.MapMan.MapExists(gridsRule.Map));
var nukieMap = mapSys.GetMap(gridsRule.Map!.Value);
var targetStation = entMan.GetComponent<StationDataComponent>(rule.TargetStation!.Value);
var targetStation = entMan.GetComponent<StationDataComponent>(ruleComp.TargetStation!.Value);
var targetGrid = targetStation.Grids.First();
var targetMap = entMan.GetComponent<TransformComponent>(targetGrid).MapUid!.Value;
Assert.That(targetMap, Is.Not.EqualTo(nukieMap));
@@ -206,7 +211,7 @@ public sealed class NukeOpsTest
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));
Assert.That(LifeStage(ruleComp.TargetStation), Is.GreaterThan(EntityLifeStage.Initialized));
// Make sure the player has hands. We've had fucking disarmed nukies before.
Assert.That(entMan.HasComponent<HandsComponent>(player));
@@ -222,10 +227,10 @@ public sealed class NukeOpsTest
}
Assert.That(total, Is.GreaterThan(3));
// Finally lets check the nukie commander passed basic training and figured out how to breathe.
// 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 increment = 5;
var resp = entMan.GetComponent<RespiratorComponent>(player);
var damage = entMan.GetComponent<DamageableComponent>(player);
for (var tick = 0; tick < totalTicks; tick += increment)
@@ -235,7 +240,24 @@ public sealed class NukeOpsTest
Assert.That(damage.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
}
ticker.SetGamePreset((GamePresetPrototype?)null);
// Check that the round does not end prematurely when agents are deleted in the outpost
var nukies = dummyEnts.Where(entMan.HasComponent<NukeOperativeComponent>).Append(player).ToArray();
await server.WaitAssertion(() =>
{
for (var i = 0; i < nukies.Length - 1; i++)
{
entMan.DeleteEntity(nukies[i]);
Assert.That(roundEndSys.IsRoundEndRequested, Is.False,
$"The round ended, but {nukies.Length - i - 1} nukies are still alive!");
}
// Delete the last nukie and make sure the round ends.
entMan.DeleteEntity(nukies[^1]);
Assert.That(roundEndSys.IsRoundEndRequested,
"All nukies were deleted, but the round didn't end!");
});
ticker.SetGamePreset((GamePresetPrototype?) null);
await pair.CleanReturnAsync();
}
}

View File

@@ -34,29 +34,25 @@ namespace Content.IntegrationTests.Tests
var testMap = await pair.CreateTestMap();
EntityUid generator = default;
var entityMan = server.ResolveDependency<IEntityManager>();
var mapMan = server.ResolveDependency<IMapManager>();
var entityMan = server.EntMan;
var mapMan = server.MapMan;
var mapSys = entityMan.System<SharedMapSystem>();
MapGridComponent grid1 = null;
MapGridComponent grid2 = null;
EntityUid grid1Entity = default!;
EntityUid grid2Entity = default!;
EntityUid generator = default;
Entity<MapGridComponent> grid1 = default;
Entity<MapGridComponent> grid2 = default;
// Create grids
await server.WaitAssertion(() =>
{
var mapId = testMap.MapId;
grid1 = mapMan.CreateGrid(mapId);
grid2 = mapMan.CreateGrid(mapId);
grid1Entity = grid1.Owner;
grid2Entity = grid2.Owner;
grid1 = mapMan.CreateGridEntity(mapId);
grid2 = mapMan.CreateGridEntity(mapId);
mapSys.SetTile(grid1Entity, grid1, Vector2i.Zero, new Tile(1));
mapSys.SetTile(grid2Entity, grid2, Vector2i.Zero, new Tile(1));
mapSys.SetTile(grid1, grid1, Vector2i.Zero, new Tile(1));
mapSys.SetTile(grid2, grid2, Vector2i.Zero, new Tile(1));
generator = entityMan.SpawnEntity("GridGravityGeneratorDummy", new EntityCoordinates(grid1Entity, 0.5f, 0.5f));
generator = entityMan.SpawnEntity("GridGravityGeneratorDummy", new EntityCoordinates(grid1, 0.5f, 0.5f));
Assert.Multiple(() =>
{
Assert.That(entityMan.HasComponent<GravityGeneratorComponent>(generator));
@@ -77,8 +73,8 @@ namespace Content.IntegrationTests.Tests
Assert.Multiple(() =>
{
Assert.That(generatorComponent.GravityActive, Is.True);
Assert.That(!entityMan.GetComponent<GravityComponent>(grid1Entity).EnabledVV);
Assert.That(entityMan.GetComponent<GravityComponent>(grid2Entity).EnabledVV);
Assert.That(!entityMan.GetComponent<GravityComponent>(grid1).EnabledVV);
Assert.That(entityMan.GetComponent<GravityComponent>(grid2).EnabledVV);
});
// Re-enable needs power so it turns off again.
@@ -95,7 +91,7 @@ namespace Content.IntegrationTests.Tests
Assert.Multiple(() =>
{
Assert.That(generatorComponent.GravityActive, Is.False);
Assert.That(entityMan.GetComponent<GravityComponent>(grid2Entity).EnabledVV, Is.False);
Assert.That(entityMan.GetComponent<GravityComponent>(grid2).EnabledVV, Is.False);
});
});

View File

@@ -48,13 +48,9 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
var sysMan = server.ResolveDependency<IEntitySystemManager>();
var handSys = sysMan.GetEntitySystem<SharedHandsSystem>();
var mapId = MapId.Nullspace;
var coords = MapCoordinates.Nullspace;
await server.WaitAssertion(() =>
{
mapId = mapManager.CreateMap();
coords = new MapCoordinates(Vector2.Zero, mapId);
});
var map = await pair.CreateTestMap();
var mapId = map.MapId;
var coords = map.MapCoords;
await server.WaitIdleAsync();
EntityUid user = default;
@@ -119,13 +115,9 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
var sysMan = server.ResolveDependency<IEntitySystemManager>();
var handSys = sysMan.GetEntitySystem<SharedHandsSystem>();
var mapId = MapId.Nullspace;
var coords = MapCoordinates.Nullspace;
await server.WaitAssertion(() =>
{
mapId = mapManager.CreateMap();
coords = new MapCoordinates(Vector2.Zero, mapId);
});
var map = await pair.CreateTestMap();
var mapId = map.MapId;
var coords = map.MapCoords;
await server.WaitIdleAsync();
EntityUid user = default;
@@ -190,13 +182,9 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
var sysMan = server.ResolveDependency<IEntitySystemManager>();
var handSys = sysMan.GetEntitySystem<SharedHandsSystem>();
var mapId = MapId.Nullspace;
var coords = MapCoordinates.Nullspace;
await server.WaitAssertion(() =>
{
mapId = mapManager.CreateMap();
coords = new MapCoordinates(Vector2.Zero, mapId);
});
var map = await pair.CreateTestMap();
var mapId = map.MapId;
var coords = map.MapCoords;
await server.WaitIdleAsync();
EntityUid user = default;
@@ -261,13 +249,9 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
var sysMan = server.ResolveDependency<IEntitySystemManager>();
var handSys = sysMan.GetEntitySystem<SharedHandsSystem>();
var mapId = MapId.Nullspace;
var coords = MapCoordinates.Nullspace;
await server.WaitAssertion(() =>
{
mapId = mapManager.CreateMap();
coords = new MapCoordinates(Vector2.Zero, mapId);
});
var map = await pair.CreateTestMap();
var mapId = map.MapId;
var coords = map.MapCoords;
await server.WaitIdleAsync();
EntityUid user = default;
@@ -331,13 +315,9 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
var handSys = sysMan.GetEntitySystem<SharedHandsSystem>();
var conSystem = sysMan.GetEntitySystem<SharedContainerSystem>();
var mapId = MapId.Nullspace;
var coords = MapCoordinates.Nullspace;
await server.WaitAssertion(() =>
{
mapId = mapManager.CreateMap();
coords = new MapCoordinates(Vector2.Zero, mapId);
});
var map = await pair.CreateTestMap();
var mapId = map.MapId;
var coords = map.MapCoords;
await server.WaitIdleAsync();
EntityUid user = default;

View File

@@ -39,10 +39,11 @@ namespace Content.IntegrationTests.Tests.Interaction
EntityUid other = default;
MapCoordinates mapCoordinates = default;
var map = await pair.CreateTestMap();
await server.WaitAssertion(() =>
{
var mapId = mapManager.CreateMap();
var coordinates = new MapCoordinates(Vector2.Zero, mapId);
var coordinates = map.MapCoords;
origin = sEntities.SpawnEntity(HumanId, coordinates);
other = sEntities.SpawnEntity(HumanId, coordinates);

View File

@@ -571,11 +571,11 @@ public abstract partial class InteractionTest
var tile = Tile.Empty;
var serverCoords = SEntMan.GetCoordinates(coords ?? TargetCoords);
var pos = serverCoords.ToMap(SEntMan, Transform);
var pos = Transform.ToMapCoordinates(serverCoords);
await Server.WaitPost(() =>
{
if (MapMan.TryFindGridAt(pos, out _, out var grid))
tile = grid.GetTileRef(serverCoords).Tile;
if (MapMan.TryFindGridAt(pos, out var gridUid, out var grid))
tile = MapSystem.GetTileRef(gridUid, grid, serverCoords).Tile;
});
Assert.That(tile.TypeId, Is.EqualTo(targetTile.TypeId));
@@ -757,33 +757,41 @@ public abstract partial class InteractionTest
/// <summary>
/// Set the tile at the target position to some prototype.
/// </summary>
protected async Task SetTile(string? proto, NetCoordinates? coords = null, MapGridComponent? grid = null)
protected async Task SetTile(string? proto, NetCoordinates? coords = null, Entity<MapGridComponent>? grid = null)
{
var tile = proto == null
? Tile.Empty
: new Tile(TileMan[proto].TileId);
var pos = SEntMan.GetCoordinates(coords ?? TargetCoords).ToMap(SEntMan, Transform);
var pos = Transform.ToMapCoordinates(SEntMan.GetCoordinates(coords ?? TargetCoords));
EntityUid gridUid;
MapGridComponent? gridComp;
await Server.WaitPost(() =>
{
if (grid != null || MapMan.TryFindGridAt(pos, out var gridUid, out grid))
if (grid is { } gridEnt)
{
grid.SetTile(SEntMan.GetCoordinates(coords ?? TargetCoords), tile);
MapSystem.SetTile(gridEnt, SEntMan.GetCoordinates(coords ?? TargetCoords), tile);
return;
}
else if (MapMan.TryFindGridAt(pos, out var gUid, out var gComp))
{
MapSystem.SetTile(gUid, gComp, SEntMan.GetCoordinates(coords ?? TargetCoords), tile);
return;
}
if (proto == null)
return;
var gridEnt = MapMan.CreateGridEntity(MapData.MapId);
gridEnt = MapMan.CreateGridEntity(MapData.MapId);
grid = gridEnt;
gridUid = gridEnt;
gridComp = gridEnt.Comp;
var gridXform = SEntMan.GetComponent<TransformComponent>(gridUid);
Transform.SetWorldPosition(gridXform, pos.Position);
grid.SetTile(SEntMan.GetCoordinates(coords ?? TargetCoords), tile);
MapSystem.SetTile((gridUid, gridComp), SEntMan.GetCoordinates(coords ?? TargetCoords), tile);
if (!MapMan.TryFindGridAt(pos, out _, out grid))
if (!MapMan.TryFindGridAt(pos, out _, out _))
Assert.Fail("Failed to create grid?");
});
await AssertTile(proto, coords);

View File

@@ -1,5 +1,4 @@
#nullable enable
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using Content.Client.Construction;
@@ -108,6 +107,7 @@ public abstract partial class InteractionTest
protected SharedItemToggleSystem ItemToggleSys = default!;
protected InteractionTestSystem STestSystem = default!;
protected SharedTransformSystem Transform = default!;
protected SharedMapSystem MapSystem = default!;
protected ISawmill SLogger = default!;
protected SharedUserInterfaceSystem SUiSys = default!;
@@ -153,7 +153,7 @@ public abstract partial class InteractionTest
[SetUp]
public virtual async Task Setup()
{
Pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, Dirty = true});
Pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, Dirty = true });
// server dependencies
SEntMan = Server.ResolveDependency<IEntityManager>();
@@ -168,6 +168,7 @@ public abstract partial class InteractionTest
ItemToggleSys = SEntMan.System<SharedItemToggleSystem>();
DoAfterSys = SEntMan.System<SharedDoAfterSystem>();
Transform = SEntMan.System<SharedTransformSystem>();
MapSystem = SEntMan.System<SharedMapSystem>();
SConstruction = SEntMan.System<Server.Construction.ConstructionSystem>();
STestSystem = SEntMan.System<InteractionTestSystem>();
Stack = SEntMan.System<StackSystem>();
@@ -188,9 +189,10 @@ public abstract partial class InteractionTest
// Setup map.
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.Grid.Comp);
PlayerCoords = SEntMan.GetNetCoordinates(Transform.WithEntityId(MapData.GridCoords.Offset(new Vector2(0.5f, 0.5f)), MapData.MapUid));
TargetCoords = SEntMan.GetNetCoordinates(Transform.WithEntityId(MapData.GridCoords.Offset(new Vector2(1.5f, 0.5f)), MapData.MapUid));
await SetTile(Plating, grid: MapData.Grid);
// Get player data
var sPlayerMan = Server.ResolveDependency<Robust.Server.Player.IPlayerManager>();
@@ -263,7 +265,8 @@ public abstract partial class InteractionTest
await TearDown();
}
protected virtual async Task TearDown()
protected virtual Task TearDown()
{
return Task.CompletedTask;
}
}

View File

@@ -26,26 +26,26 @@ public sealed class StaticFieldValidationTest
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));
Assert.That(protoMan.ValidateStaticFields(typeof(StringValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(StringArrayValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(EntProtoIdValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(EntProtoIdArrayValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdTestValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdArrayValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdListValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdSetValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(PrivateProtoIdArrayValid), protos), Is.Empty);
Assert.That(protoMan.ValidateStaticFields(typeof(StringInvalid), protos), Has.Count.EqualTo(1));
Assert.That(protoMan.ValidateStaticFields(typeof(StringArrayInvalid), protos), Has.Count.EqualTo(2));
Assert.That(protoMan.ValidateStaticFields(typeof(EntProtoIdInvalid), protos), Has.Count.EqualTo(1));
Assert.That(protoMan.ValidateStaticFields(typeof(EntProtoIdArrayInvalid), protos), Has.Count.EqualTo(2));
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdTestInvalid), protos), Has.Count.EqualTo(1));
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdArrayInvalid), protos), Has.Count.EqualTo(2));
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdListInvalid), protos), Has.Count.EqualTo(2));
Assert.That(protoMan.ValidateStaticFields(typeof(ProtoIdSetInvalid), protos), Has.Count.EqualTo(2));
Assert.That(protoMan.ValidateStaticFields(typeof(PrivateProtoIdArrayInvalid), protos), Has.Count.EqualTo(2));
await pair.CleanReturnAsync();
}
@@ -58,93 +58,111 @@ public sealed class StaticFieldValidationTest
id: StaticFieldTestTag
";
[Reflect(false)] private sealed class StringValid
[Reflect(false)]
private sealed class StringValid
{
[ValidatePrototypeId<TagPrototype>] public static string Tag = "StaticFieldTestTag";
}
[Reflect(false)] private sealed class StringInvalid
[Reflect(false)]
private sealed class StringInvalid
{
[ValidatePrototypeId<TagPrototype>] public static string Tag = string.Empty;
}
[Reflect(false)] private sealed class StringArrayValid
[Reflect(false)]
private sealed class StringArrayValid
{
[ValidatePrototypeId<TagPrototype>] public static string[] Tag = {"StaticFieldTestTag", "StaticFieldTestTag"};
[ValidatePrototypeId<TagPrototype>] public static string[] Tag = ["StaticFieldTestTag", "StaticFieldTestTag"];
}
[Reflect(false)] private sealed class StringArrayInvalid
[Reflect(false)]
private sealed class StringArrayInvalid
{
[ValidatePrototypeId<TagPrototype>] public static string[] Tag = {string.Empty, "StaticFieldTestTag", string.Empty};
[ValidatePrototypeId<TagPrototype>] public static string[] Tag = [string.Empty, "StaticFieldTestTag", string.Empty];
}
[Reflect(false)] private sealed class EntProtoIdValid
[Reflect(false)]
private sealed class EntProtoIdValid
{
public static EntProtoId Tag = "StaticFieldTestEnt";
}
[Reflect(false)] private sealed class EntProtoIdInvalid
[Reflect(false)]
private sealed class EntProtoIdInvalid
{
public static EntProtoId Tag = string.Empty;
}
[Reflect(false)] private sealed class EntProtoIdArrayValid
[Reflect(false)]
private sealed class EntProtoIdArrayValid
{
public static EntProtoId[] Tag = {"StaticFieldTestEnt", "StaticFieldTestEnt"};
public static EntProtoId[] Tag = ["StaticFieldTestEnt", "StaticFieldTestEnt"];
}
[Reflect(false)] private sealed class EntProtoIdArrayInvalid
[Reflect(false)]
private sealed class EntProtoIdArrayInvalid
{
public static EntProtoId[] Tag = {string.Empty, "StaticFieldTestEnt", string.Empty};
public static EntProtoId[] Tag = [string.Empty, "StaticFieldTestEnt", string.Empty];
}
[Reflect(false)] private sealed class ProtoIdTestValid
[Reflect(false)]
private sealed class ProtoIdTestValid
{
public static ProtoId<TagPrototype> Tag = "StaticFieldTestTag";
}
[Reflect(false)] private sealed class ProtoIdTestInvalid
[Reflect(false)]
private sealed class ProtoIdTestInvalid
{
public static ProtoId<TagPrototype> Tag = string.Empty;
}
[Reflect(false)] private sealed class ProtoIdArrayValid
[Reflect(false)]
private sealed class ProtoIdArrayValid
{
public static ProtoId<TagPrototype>[] Tag = {"StaticFieldTestTag", "StaticFieldTestTag"};
public static ProtoId<TagPrototype>[] Tag = ["StaticFieldTestTag", "StaticFieldTestTag"];
}
[Reflect(false)] private sealed class ProtoIdArrayInvalid
[Reflect(false)]
private sealed class ProtoIdArrayInvalid
{
public static ProtoId<TagPrototype>[] Tag = {string.Empty, "StaticFieldTestTag", string.Empty};
public static ProtoId<TagPrototype>[] Tag = [string.Empty, "StaticFieldTestTag", string.Empty];
}
[Reflect(false)] private sealed class ProtoIdListValid
[Reflect(false)]
private sealed class ProtoIdListValid
{
public static List<ProtoId<TagPrototype>> Tag = new() {"StaticFieldTestTag", "StaticFieldTestTag"};
public static List<ProtoId<TagPrototype>> Tag = ["StaticFieldTestTag", "StaticFieldTestTag"];
}
[Reflect(false)] private sealed class ProtoIdListInvalid
[Reflect(false)]
private sealed class ProtoIdListInvalid
{
public static List<ProtoId<TagPrototype>> Tag = new() {string.Empty, "StaticFieldTestTag", string.Empty};
public static List<ProtoId<TagPrototype>> Tag = [string.Empty, "StaticFieldTestTag", string.Empty];
}
[Reflect(false)] private sealed class ProtoIdSetValid
[Reflect(false)]
private sealed class ProtoIdSetValid
{
public static HashSet<ProtoId<TagPrototype>> Tag = new() {"StaticFieldTestTag", "StaticFieldTestTag"};
public static HashSet<ProtoId<TagPrototype>> Tag = ["StaticFieldTestTag", "StaticFieldTestTag"];
}
[Reflect(false)] private sealed class ProtoIdSetInvalid
[Reflect(false)]
private sealed class ProtoIdSetInvalid
{
public static HashSet<ProtoId<TagPrototype>> Tag = new() {string.Empty, "StaticFieldTestTag", string.Empty, " "};
public static HashSet<ProtoId<TagPrototype>> Tag = [string.Empty, "StaticFieldTestTag", string.Empty, " "];
}
[Reflect(false)] private sealed class PrivateProtoIdArrayValid
[Reflect(false)]
private sealed class PrivateProtoIdArrayValid
{
private static ProtoId<TagPrototype>[] Tag = {"StaticFieldTestTag", "StaticFieldTestTag"};
private static readonly ProtoId<TagPrototype>[] Tag = ["StaticFieldTestTag", "StaticFieldTestTag"];
}
[Reflect(false)] private sealed class PrivateProtoIdArrayInvalid
[Reflect(false)]
private sealed class PrivateProtoIdArrayInvalid
{
private static ProtoId<TagPrototype>[] Tag = {string.Empty, "StaticFieldTestTag", string.Empty};
private static readonly ProtoId<TagPrototype>[] Tag = [string.Empty, "StaticFieldTestTag", string.Empty];
}
}

View File

@@ -2,7 +2,6 @@
using System.Linq;
using Content.Server.Construction.Components;
using Content.Shared.Construction.Components;
using Content.Shared.Prototypes;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
@@ -37,6 +36,7 @@ public sealed class MachineBoardTest
var server = pair.Server;
var protoMan = server.ResolveDependency<IPrototypeManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
await server.WaitAssertion(() =>
{
@@ -45,7 +45,7 @@ public sealed class MachineBoardTest
.Where(p => !pair.IsTestPrototype(p))
.Where(p => !_ignoredPrototypes.Contains(p.ID)))
{
if (!p.TryGetComponent<MachineBoardComponent>(out var mbc))
if (!p.TryGetComponent<MachineBoardComponent>(out var mbc, compFact))
continue;
var mId = mbc.Prototype;
@@ -53,7 +53,7 @@ public sealed class MachineBoardTest
{
Assert.That(protoMan.TryIndex<EntityPrototype>(mId, out var mProto),
$"Machine board {p.ID}'s corresponding machine has an invalid prototype.");
Assert.That(mProto.TryGetComponent<MachineComponent>(out var mComp),
Assert.That(mProto.TryGetComponent<MachineComponent>(out var mComp, compFact),
$"Machine board {p.ID}'s corresponding machine {mId} does not have MachineComponent");
Assert.That(mComp.Board, Is.EqualTo(p.ID),
$"Machine {mId}'s BoardPrototype is not equal to it's corresponding machine board, {p.ID}");
@@ -75,6 +75,7 @@ public sealed class MachineBoardTest
var server = pair.Server;
var protoMan = server.ResolveDependency<IPrototypeManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
await server.WaitAssertion(() =>
{
@@ -83,7 +84,7 @@ public sealed class MachineBoardTest
.Where(p => !pair.IsTestPrototype(p))
.Where(p => !_ignoredPrototypes.Contains(p.ID)))
{
if (!p.TryGetComponent<ComputerBoardComponent>(out var cbc))
if (!p.TryGetComponent<ComputerBoardComponent>(out var cbc, compFact))
continue;
var cId = cbc.Prototype;
@@ -92,7 +93,7 @@ public sealed class MachineBoardTest
Assert.That(cId, Is.Not.Null, $"Computer board \"{p.ID}\" does not have a corresponding computer.");
Assert.That(protoMan.TryIndex<EntityPrototype>(cId, out var cProto),
$"Computer board \"{p.ID}\"'s corresponding computer has an invalid prototype.");
Assert.That(cProto.TryGetComponent<ComputerComponent>(out var cComp),
Assert.That(cProto.TryGetComponent<ComputerComponent>(out var cComp, compFact),
$"Computer board {p.ID}'s corresponding computer \"{cId}\" does not have ComputerComponent");
Assert.That(cComp.BoardPrototype, Is.EqualTo(p.ID),
$"Computer \"{cId}\"'s BoardPrototype is not equal to it's corresponding computer board, \"{p.ID}\"");

View File

@@ -13,7 +13,7 @@ public sealed class MappingTests
[Test]
public async Task MappingTest()
{
await using var pair = await PoolManager.GetServerClient(new PoolSettings {Dirty = true, Connected = true, DummyTicker = false});
await using var pair = await PoolManager.GetServerClient(new PoolSettings { Dirty = true, Connected = true, DummyTicker = false });
var server = pair.Server;
var entMan = server.EntMan;

View File

@@ -38,15 +38,16 @@ public sealed class MaterialArbitrageTest
await server.WaitIdleAsync();
var entManager = server.ResolveDependency<IEntityManager>();
var sysManager = server.ResolveDependency<IEntitySystemManager>();
var mapManager = server.ResolveDependency<IMapManager>();
Assert.That(mapManager.IsMapInitialized(testMap.MapId));
var protoManager = server.ResolveDependency<IPrototypeManager>();
var pricing = sysManager.GetEntitySystem<PricingSystem>();
var stackSys = sysManager.GetEntitySystem<StackSystem>();
var pricing = entManager.System<PricingSystem>();
var stackSys = entManager.System<StackSystem>();
var mapSystem = server.System<SharedMapSystem>();
var compFact = server.ResolveDependency<IComponentFactory>();
Assert.That(mapSystem.IsInitialized(testMap.MapId));
var constructionName = compFact.GetComponentName(typeof(ConstructionComponent));
var compositionName = compFact.GetComponentName(typeof(PhysicalCompositionComponent));
var materialName = compFact.GetComponentName(typeof(MaterialComponent));
@@ -67,7 +68,7 @@ public sealed class MaterialArbitrageTest
Dictionary<string, ConstructionComponent> constructionRecipes = new();
foreach (var proto in protoManager.EnumeratePrototypes<EntityPrototype>())
{
if (proto.NoSpawn || proto.Abstract || pair.IsTestPrototype(proto))
if (proto.HideSpawnMenu || proto.Abstract || pair.IsTestPrototype(proto))
continue;
if (!proto.Components.TryGetValue(constructionName, out var destructible))
@@ -127,7 +128,7 @@ public sealed class MaterialArbitrageTest
// Here we get the set of entities/materials spawned when destroying an entity.
foreach (var proto in protoManager.EnumeratePrototypes<EntityPrototype>())
{
if (proto.NoSpawn || proto.Abstract || pair.IsTestPrototype(proto))
if (proto.HideSpawnMenu || proto.Abstract || pair.IsTestPrototype(proto))
continue;
if (!proto.Components.TryGetValue(destructibleName, out var destructible))
@@ -298,7 +299,7 @@ public sealed class MaterialArbitrageTest
Dictionary<string, PhysicalCompositionComponent> physicalCompositions = new();
foreach (var proto in protoManager.EnumeratePrototypes<EntityPrototype>())
{
if (proto.NoSpawn || proto.Abstract || pair.IsTestPrototype(proto))
if (proto.HideSpawnMenu || proto.Abstract || pair.IsTestPrototype(proto))
continue;
if (!proto.Components.TryGetValue(compositionName, out var composition))

View File

@@ -14,7 +14,7 @@ namespace Content.IntegrationTests.Tests.Minds;
[TestFixture]
public sealed class GhostTests
{
struct GhostTestData
private struct GhostTestData
{
public IEntityManager SEntMan;
public Robust.Server.Player.IPlayerManager SPlayerMan;
@@ -23,10 +23,10 @@ public sealed class GhostTests
public TestPair Pair = default!;
public TestMapData MapData => Pair.TestMap!;
public readonly TestMapData MapData => Pair.TestMap!;
public RobustIntegrationTest.ServerIntegrationInstance Server => Pair.Server;
public RobustIntegrationTest.ClientIntegrationInstance Client => Pair.Client;
public readonly RobustIntegrationTest.ServerIntegrationInstance Server => Pair.Server;
public readonly RobustIntegrationTest.ClientIntegrationInstance Client => Pair.Client;
/// <summary>
/// Initial player coordinates. Note that this does not necessarily correspond to the position of the
@@ -47,15 +47,16 @@ public sealed class GhostTests
private async Task<GhostTestData> SetupData()
{
var data = new GhostTestData();
// Client is needed to create a session for the ghost system. Creating a dummy session was too difficult.
data.Pair = await PoolManager.GetServerClient(new PoolSettings
var data = new GhostTestData
{
DummyTicker = false,
Connected = true,
Dirty = true
});
// Client is needed to create a session for the ghost system. Creating a dummy session was too difficult.
Pair = await PoolManager.GetServerClient(new PoolSettings
{
DummyTicker = false,
Connected = true,
Dirty = true
})
};
data.SEntMan = data.Pair.Server.ResolveDependency<IServerEntityManager>();
data.SPlayerMan = data.Pair.Server.ResolveDependency<Robust.Server.Player.IPlayerManager>();
@@ -64,7 +65,8 @@ public sealed class GhostTests
// Setup map.
await data.Pair.CreateTestMap();
data.PlayerCoords = data.SEntMan.GetNetCoordinates(data.MapData.GridCoords.Offset(new Vector2(0.5f, 0.5f)).WithEntityId(data.MapData.MapUid, data.STransformSys, data.SEntMan));
var test = data.MapData.GridCoords.Offset(new Vector2(0.5f, 0.5f));
data.PlayerCoords = data.SEntMan.GetNetCoordinates(data.STransformSys.WithEntityId(data.MapData.GridCoords.Offset(new Vector2(0.5f, 0.5f)), data.MapData.MapUid));
if (data.Client.Session == null)
Assert.Fail("No player");

View File

@@ -169,7 +169,7 @@ public sealed partial class MindTests
{
var netManager = pair.Client.ResolveDependency<IClientNetManager>();
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
Assert.That(!playerMan.Sessions.Any());
Assert.That(playerMan.Sessions, Is.Empty);
await Task.WhenAll(pair.Client.WaitIdleAsync(), pair.Client.WaitIdleAsync());
pair.Client.SetConnectTarget(pair.Server);

View File

@@ -34,7 +34,7 @@ public sealed class BuckleMovementTest : MovementTest
Assert.That(Delta(), Is.InRange(-0.01f, 0.01f));
Assert.That(buckle.Buckled, Is.True);
Assert.That(buckle.BuckledTo, Is.EqualTo(STarget));
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[]{SPlayer}));
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[] { SPlayer }));
Assert.That(cAlert.IsShowingAlert(CPlayer, strap.BuckledAlertType), Is.True);
Assert.That(sAlert.IsShowingAlert(SPlayer, strap.BuckledAlertType), Is.True);
@@ -43,7 +43,7 @@ public sealed class BuckleMovementTest : MovementTest
Assert.That(Delta(), Is.InRange(-0.01f, 0.01f));
Assert.That(buckle.Buckled, Is.True);
Assert.That(buckle.BuckledTo, Is.EqualTo(STarget));
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[]{SPlayer}));
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[] { SPlayer }));
Assert.That(cAlert.IsShowingAlert(CPlayer, strap.BuckledAlertType), Is.True);
Assert.That(sAlert.IsShowingAlert(SPlayer, strap.BuckledAlertType), Is.True);

View File

@@ -32,7 +32,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.Grid.Comp);
await SetTile(Plating, SEntMan.GetNetCoordinates(pCoords.Offset(new Vector2(i, 0))), MapData.Grid);
}
AssertGridCount(1);

View File

@@ -7,12 +7,12 @@ namespace Content.IntegrationTests.Tests.Networking;
[TestFixture]
public sealed class PvsCommandTest
{
public static EntProtoId TestEnt = "MobHuman";
private static readonly EntProtoId TestEnt = "MobHuman";
[Test]
public async Task TestPvsCommands()
{
await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false});
await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false });
var (server, client) = pair;
await pair.RunTicksSync(5);

View File

@@ -51,11 +51,12 @@ namespace Content.IntegrationTests.Tests.Networking
PredictionTestComponent clientComponent = default!;
var serverSystem = sEntityManager.System<PredictionTestEntitySystem>();
var clientSystem = cEntityManager.System<PredictionTestEntitySystem>();
var sMapSys = sEntityManager.System<SharedMapSystem>();
await server.WaitPost(() =>
{
// Spawn dummy component entity.
var map = sMapManager.CreateMap();
sMapSys.CreateMap(out var map);
serverEnt = sEntityManager.SpawnEntity(null, new MapCoordinates(new Vector2(0, 0), map));
serverComponent = sEntityManager.AddComponent<PredictionTestComponent>(serverEnt);
});
@@ -67,7 +68,7 @@ namespace Content.IntegrationTests.Tests.Networking
Assert.That(sGameTiming.TickTimingAdjustment, Is.EqualTo(0));
// Check client buffer is full
Assert.That(cGameStateManager.CurrentBufferSize, Is.EqualTo(cGameStateManager.TargetBufferSize));
Assert.That(cGameStateManager.GetApplicableStateCount(), Is.EqualTo(cGameStateManager.TargetBufferSize));
Assert.That(cGameStateManager.TargetBufferSize, Is.EqualTo(2));
// This isn't required anymore, but the test had this for the sake of "technical things", and I cbf shifting
@@ -99,7 +100,7 @@ namespace Content.IntegrationTests.Tests.Networking
// Client last ran tick 15 meaning it's ahead of the last server tick it processed (12)
Assert.That(cGameTiming.CurTick, Is.EqualTo(expected));
Assert.That(cGameTiming.LastProcessedTick, Is.EqualTo(new GameTick((uint)(baseTick - cGameStateManager.TargetBufferSize))));
Assert.That(cGameTiming.LastProcessedTick, Is.EqualTo(new GameTick((uint) (baseTick - cGameStateManager.TargetBufferSize))));
});
// *** I am using block scopes to visually distinguish these sections of the test to make it more readable.
@@ -264,7 +265,7 @@ namespace Content.IntegrationTests.Tests.Networking
// Assert timing is still correct.
Assert.That(sGameTiming.CurTick, Is.EqualTo(new GameTick(baseTick + 8)));
Assert.That(cGameTiming.CurTick, Is.EqualTo(new GameTick(baseTick + 8 + delta)));
Assert.That(cGameTiming.LastProcessedTick, Is.EqualTo(new GameTick((uint)(baseTick + 8 - cGameStateManager.TargetBufferSize))));
Assert.That(cGameTiming.LastProcessedTick, Is.EqualTo(new GameTick((uint) (baseTick + 8 - cGameStateManager.TargetBufferSize))));
});
{

View File

@@ -81,13 +81,14 @@ namespace Content.IntegrationTests.Tests
var entManager = server.ResolveDependency<IEntityManager>();
var mapLoader = entManager.System<MapLoaderSystem>();
var mapSystem = entManager.System<SharedMapSystem>();
var mapManager = server.ResolveDependency<IMapManager>();
var cfg = server.ResolveDependency<IConfigurationManager>();
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
await server.WaitPost(() =>
{
var mapId = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId);
try
{
#pragma warning disable NUnit2045
@@ -168,6 +169,7 @@ namespace Content.IntegrationTests.Tests
var mapManager = server.ResolveDependency<IMapManager>();
var entManager = server.ResolveDependency<IEntityManager>();
var mapLoader = entManager.System<MapLoaderSystem>();
var mapSystem = entManager.System<SharedMapSystem>();
var protoManager = server.ResolveDependency<IPrototypeManager>();
var ticker = entManager.EntitySysManager.GetEntitySystem<GameTicker>();
var shuttleSystem = entManager.EntitySysManager.GetEntitySystem<ShuttleSystem>();
@@ -177,7 +179,7 @@ namespace Content.IntegrationTests.Tests
await server.WaitPost(() =>
{
var mapId = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId);
try
{
ticker.LoadGameMap(protoManager.Index<GameMapPrototype>(mapProto), mapId, null);
@@ -187,7 +189,7 @@ namespace Content.IntegrationTests.Tests
throw new Exception($"Failed to load map {mapProto}", ex);
}
var shuttleMap = mapManager.CreateMap();
mapSystem.CreateMap(out var shuttleMap);
var largest = 0f;
EntityUid? targetGrid = null;
var memberQuery = entManager.GetEntityQuery<StationMemberComponent>();
@@ -256,7 +258,7 @@ namespace Content.IntegrationTests.Tests
.Select(x => x.Job!.Value);
jobs.ExceptWith(spawnPoints);
Assert.That(jobs, Is.Empty,$"There is no spawnpoints for {string.Join(", ", jobs)} on {mapProto}.");
Assert.That(jobs, Is.Empty, $"There is no spawnpoints for {string.Join(", ", jobs)} on {mapProto}.");
}
try
@@ -329,6 +331,7 @@ namespace Content.IntegrationTests.Tests
var resourceManager = server.ResolveDependency<IResourceManager>();
var protoManager = server.ResolveDependency<IPrototypeManager>();
var cfg = server.ResolveDependency<IConfigurationManager>();
var mapSystem = server.System<SharedMapSystem>();
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
var gameMaps = protoManager.EnumeratePrototypes<GameMapPrototype>().Select(o => o.MapPath).ToHashSet();
@@ -359,7 +362,7 @@ namespace Content.IntegrationTests.Tests
{
foreach (var mapName in mapNames)
{
var mapId = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId);
try
{
Assert.That(mapLoader.TryLoad(mapId, mapName, out _));

View File

@@ -166,6 +166,7 @@ namespace Content.IntegrationTests.Tests.Power
var server = pair.Server;
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var mapSys = entityManager.System<SharedMapSystem>();
const float loadPower = 200;
PowerSupplierComponent supplier = default!;
PowerConsumerComponent consumer1 = default!;
@@ -173,21 +174,19 @@ namespace Content.IntegrationTests.Tests.Power
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 3; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates());
var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 1));
var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 2));
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates());
var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 1));
var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 2));
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
consumer1 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
@@ -229,6 +228,7 @@ namespace Content.IntegrationTests.Tests.Power
var server = pair.Server;
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var mapSys = entityManager.System<SharedMapSystem>();
const float loadPower = 200;
PowerSupplierComponent supplier = default!;
PowerConsumerComponent consumer1 = default!;
@@ -236,21 +236,19 @@ namespace Content.IntegrationTests.Tests.Power
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 3; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates());
var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 1));
var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 2));
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates());
var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 1));
var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 2));
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
consumer1 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
@@ -288,25 +286,25 @@ namespace Content.IntegrationTests.Tests.Power
var server = pair.Server;
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var mapSys = entityManager.System<SharedMapSystem>();
var gameTiming = server.ResolveDependency<IGameTiming>();
PowerSupplierComponent supplier = default!;
PowerConsumerComponent consumer = default!;
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 3; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates());
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 2));
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates());
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 2));
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
consumer = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
@@ -378,6 +376,7 @@ namespace Content.IntegrationTests.Tests.Power
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTiming = server.ResolveDependency<IGameTiming>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
const float startingCharge = 100_000;
PowerNetworkBatteryComponent netBattery = default!;
@@ -386,19 +385,18 @@ namespace Content.IntegrationTests.Tests.Power
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 3; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var generatorEnt = entityManager.SpawnEntity("DischargingBatteryDummy", gridOwner.ToCoordinates());
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 2));
var generatorEnt = entityManager.SpawnEntity("DischargingBatteryDummy", grid.Owner.ToCoordinates());
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 2));
netBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(generatorEnt);
battery = entityManager.GetComponent<BatteryComponent>(generatorEnt);
@@ -479,6 +477,7 @@ namespace Content.IntegrationTests.Tests.Power
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerSupplierComponent supplier = default!;
PowerNetworkBatteryComponent netBattery = default!;
BatteryComponent battery = default!;
@@ -490,20 +489,19 @@ namespace Content.IntegrationTests.Tests.Power
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 3; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates());
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 1));
var batteryEnt = entityManager.SpawnEntity("DischargingBatteryDummy", gridOwner.ToCoordinates(0, 2));
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates());
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 1));
var batteryEnt = entityManager.SpawnEntity("DischargingBatteryDummy", grid.Owner.ToCoordinates(0, 2));
netBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
battery = entityManager.GetComponent<BatteryComponent>(batteryEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
@@ -577,24 +575,24 @@ namespace Content.IntegrationTests.Tests.Power
var gameTiming = server.ResolveDependency<IGameTiming>();
var entityManager = server.ResolveDependency<IEntityManager>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerSupplierComponent supplier = default!;
BatteryComponent battery = default!;
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 3; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates());
var batteryEnt = entityManager.SpawnEntity("ChargingBatteryDummy", gridOwner.ToCoordinates(0, 2));
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates());
var batteryEnt = entityManager.SpawnEntity("ChargingBatteryDummy", grid.Owner.ToCoordinates(0, 2));
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
var netBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
@@ -634,6 +632,7 @@ namespace Content.IntegrationTests.Tests.Power
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTiming = server.ResolveDependency<IGameTiming>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerConsumerComponent consumer = default!;
PowerSupplierComponent supplier = default!;
PowerNetworkBatteryComponent netBattery = default!;
@@ -641,23 +640,22 @@ namespace Content.IntegrationTests.Tests.Power
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 4; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var terminal = entityManager.SpawnEntity("CableTerminal", gridOwner.ToCoordinates(0, 1));
var terminal = entityManager.SpawnEntity("CableTerminal", grid.Owner.ToCoordinates(0, 1));
entityManager.GetComponent<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 2));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates(0, 0));
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 3));
var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 2));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates(0, 0));
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 3));
consumer = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
@@ -712,6 +710,7 @@ namespace Content.IntegrationTests.Tests.Power
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTiming = server.ResolveDependency<IGameTiming>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerConsumerComponent consumer = default!;
PowerSupplierComponent supplier = default!;
PowerNetworkBatteryComponent netBattery = default!;
@@ -719,23 +718,22 @@ namespace Content.IntegrationTests.Tests.Power
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 4; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var terminal = entityManager.SpawnEntity("CableTerminal", gridOwner.ToCoordinates(0, 1));
var terminal = entityManager.SpawnEntity("CableTerminal", grid.Owner.ToCoordinates(0, 1));
entityManager.GetComponent<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 2));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates(0, 0));
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 3));
var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 2));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates(0, 0));
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 3));
consumer = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
@@ -789,15 +787,15 @@ namespace Content.IntegrationTests.Tests.Power
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerConsumerComponent consumer1 = default!;
PowerConsumerComponent consumer2 = default!;
PowerSupplierComponent supplier = default!;
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Map layout here is
// C - consumer
@@ -810,19 +808,19 @@ namespace Content.IntegrationTests.Tests.Power
// Power only works when anchored
for (var i = 0; i < 5; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
entityManager.SpawnEntity("CableTerminal", gridOwner.ToCoordinates(0, 2));
var terminal = entityManager.SpawnEntity("CableTerminal", gridOwner.ToCoordinates(0, 2));
entityManager.SpawnEntity("CableTerminal", grid.Owner.ToCoordinates(0, 2));
var terminal = entityManager.SpawnEntity("CableTerminal", grid.Owner.ToCoordinates(0, 2));
entityManager.GetComponent<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var batteryEnt1 = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 1));
var batteryEnt2 = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 3));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates(0, 2));
var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 0));
var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 4));
var batteryEnt1 = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 1));
var batteryEnt2 = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 3));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates(0, 2));
var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 0));
var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 4));
consumer1 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
consumer2 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt2);
@@ -887,6 +885,7 @@ namespace Content.IntegrationTests.Tests.Power
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTiming = server.ResolveDependency<IGameTiming>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerConsumerComponent consumer = default!;
PowerSupplierComponent supplier1 = default!;
PowerSupplierComponent supplier2 = default!;
@@ -897,9 +896,8 @@ namespace Content.IntegrationTests.Tests.Power
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Layout is two generators, two batteries, and one load. As to why two: because previously this test
// would fail ONLY if there were more than two batteries present, because each of them tries to supply
@@ -911,17 +909,17 @@ namespace Content.IntegrationTests.Tests.Power
// Place cables
for (var i = -2; i <= 2; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var batteryEnt1 = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 2));
var batteryEnt2 = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, -2));
var batteryEnt1 = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 2));
var batteryEnt2 = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, -2));
var supplyEnt1 = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates(0, 1));
var supplyEnt2 = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates(0, -1));
var supplyEnt1 = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates(0, 1));
var supplyEnt2 = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates(0, -1));
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 0));
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 0));
consumer = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
supplier1 = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt1);
@@ -985,15 +983,15 @@ namespace Content.IntegrationTests.Tests.Power
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerConsumerComponent consumer1 = default!;
PowerConsumerComponent consumer2 = default!;
PowerSupplierComponent supplier = default!;
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Map layout here is
// C - consumer
@@ -1006,19 +1004,19 @@ namespace Content.IntegrationTests.Tests.Power
// Power only works when anchored
for (var i = 0; i < 5; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
entityManager.SpawnEntity("CableTerminal", gridOwner.ToCoordinates(0, 2));
var terminal = entityManager.SpawnEntity("CableTerminal", gridOwner.ToCoordinates(0, 2));
entityManager.SpawnEntity("CableTerminal", grid.Owner.ToCoordinates(0, 2));
var terminal = entityManager.SpawnEntity("CableTerminal", grid.Owner.ToCoordinates(0, 2));
entityManager.GetComponent<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var batteryEnt1 = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 1));
var batteryEnt2 = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 3));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates(0, 2));
var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 0));
var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 4));
var batteryEnt1 = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 1));
var batteryEnt2 = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 3));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates(0, 2));
var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 0));
var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 4));
consumer1 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
consumer2 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt2);
@@ -1073,29 +1071,29 @@ namespace Content.IntegrationTests.Tests.Power
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerConsumerComponent consumer = default!;
PowerSupplierComponent supplier = default!;
PowerNetworkBatteryComponent netBattery = default!;
await server.WaitPost(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 4; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, i));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, i));
}
var terminal = entityManager.SpawnEntity("CableTerminal", gridOwner.ToCoordinates(0, 1));
var terminal = entityManager.SpawnEntity("CableTerminal", grid.Owner.ToCoordinates(0, 1));
entityManager.GetComponent<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 2));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates(0, 0));
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", gridOwner.ToCoordinates(0, 3));
var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 2));
var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates(0, 0));
var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.Owner.ToCoordinates(0, 3));
consumer = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
@@ -1158,6 +1156,7 @@ namespace Content.IntegrationTests.Tests.Power
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var nodeContainer = entityManager.System<NodeContainerSystem>();
var mapSys = entityManager.System<SharedMapSystem>();
CableNode leftNode = default!;
CableNode rightNode = default!;
Node batteryInput = default!;
@@ -1165,25 +1164,24 @@ namespace Content.IntegrationTests.Tests.Power
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 4; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
}
var leftEnt = entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, 0));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, 1));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, 2));
var rightEnt = entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, 3));
var leftEnt = entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, 0));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, 1));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, 2));
var rightEnt = entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, 3));
var terminal = entityManager.SpawnEntity("CableTerminal", gridOwner.ToCoordinates(0, 1));
var terminal = entityManager.SpawnEntity("CableTerminal", grid.Owner.ToCoordinates(0, 1));
entityManager.GetComponent<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var battery = entityManager.SpawnEntity("FullBatteryDummy", gridOwner.ToCoordinates(0, 2));
var battery = entityManager.SpawnEntity("FullBatteryDummy", grid.Owner.ToCoordinates(0, 2));
var batteryNodeContainer = entityManager.GetComponent<NodeContainerComponent>(battery);
if (nodeContainer.TryGetNode<CableNode>(entityManager.GetComponent<NodeContainerComponent>(leftEnt),
@@ -1224,29 +1222,29 @@ namespace Content.IntegrationTests.Tests.Power
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var batterySys = entityManager.System<BatterySystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerNetworkBatteryComponent substationNetBattery = default!;
BatteryComponent apcBattery = default!;
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
// Power only works when anchored
for (var i = 0; i < 3; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
}
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, 0));
entityManager.SpawnEntity("CableHV", gridOwner.ToCoordinates(0, 1));
entityManager.SpawnEntity("CableMV", gridOwner.ToCoordinates(0, 1));
entityManager.SpawnEntity("CableMV", gridOwner.ToCoordinates(0, 2));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, 0));
entityManager.SpawnEntity("CableHV", grid.Owner.ToCoordinates(0, 1));
entityManager.SpawnEntity("CableMV", grid.Owner.ToCoordinates(0, 1));
entityManager.SpawnEntity("CableMV", grid.Owner.ToCoordinates(0, 2));
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", gridOwner.ToCoordinates(0, 0));
var substationEnt = entityManager.SpawnEntity("SubstationDummy", gridOwner.ToCoordinates(0, 1));
var apcEnt = entityManager.SpawnEntity("ApcDummy", gridOwner.ToCoordinates(0, 2));
var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.Owner.ToCoordinates(0, 0));
var substationEnt = entityManager.SpawnEntity("SubstationDummy", grid.Owner.ToCoordinates(0, 1));
var apcEnt = entityManager.SpawnEntity("ApcDummy", grid.Owner.ToCoordinates(0, 2));
var generatorSupplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
substationNetBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(substationEnt);
@@ -1281,33 +1279,33 @@ namespace Content.IntegrationTests.Tests.Power
var entityManager = server.ResolveDependency<IEntityManager>();
var batterySys = entityManager.System<BatterySystem>();
var extensionCableSystem = entityManager.System<ExtensionCableSystem>();
var mapSys = entityManager.System<SharedMapSystem>();
PowerNetworkBatteryComponent apcNetBattery = default!;
ApcPowerReceiverComponent receiver = default!;
ApcPowerReceiverComponent unpoweredReceiver = default!;
await server.WaitAssertion(() =>
{
var map = mapManager.CreateMap();
var grid = mapManager.CreateGrid(map);
var gridOwner = grid.Owner;
var map = mapSys.CreateMap(out var mapId);
var grid = mapManager.CreateGridEntity(mapId);
const int range = 5;
// Power only works when anchored
for (var i = 0; i < range; i++)
{
grid.SetTile(new Vector2i(0, i), new Tile(1));
mapSys.SetTile(grid, new Vector2i(0, i), new Tile(1));
}
var apcEnt = entityManager.SpawnEntity("ApcDummy", gridOwner.ToCoordinates(0, 0));
var apcExtensionEnt = entityManager.SpawnEntity("CableApcExtension", gridOwner.ToCoordinates(0, 0));
var apcEnt = entityManager.SpawnEntity("ApcDummy", grid.Owner.ToCoordinates(0, 0));
var apcExtensionEnt = entityManager.SpawnEntity("CableApcExtension", grid.Owner.ToCoordinates(0, 0));
// Create a powered receiver in range (range is 0 indexed)
var powerReceiverEnt = entityManager.SpawnEntity("ApcPowerReceiverDummy", gridOwner.ToCoordinates(0, range - 1));
var powerReceiverEnt = entityManager.SpawnEntity("ApcPowerReceiverDummy", grid.Owner.ToCoordinates(0, range - 1));
receiver = entityManager.GetComponent<ApcPowerReceiverComponent>(powerReceiverEnt);
// Create an unpowered receiver outside range
var unpoweredReceiverEnt = entityManager.SpawnEntity("ApcPowerReceiverDummy", gridOwner.ToCoordinates(0, range));
var unpoweredReceiverEnt = entityManager.SpawnEntity("ApcPowerReceiverDummy", grid.Owner.ToCoordinates(0, range));
unpoweredReceiver = entityManager.GetComponent<ApcPowerReceiverComponent>(unpoweredReceiverEnt);
var battery = entityManager.GetComponent<BatteryComponent>(apcEnt);

View File

@@ -40,6 +40,7 @@ public sealed class PrototypeSaveTest
var prototypeMan = server.ResolveDependency<IPrototypeManager>();
var seriMan = server.ResolveDependency<ISerializationManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
var mapSystem = server.System<SharedMapSystem>();
var prototypes = new List<EntityPrototype>();
EntityUid uid;
@@ -77,7 +78,7 @@ public sealed class PrototypeSaveTest
await server.WaitAssertion(() =>
{
Assert.That(!mapManager.IsMapInitialized(mapId));
Assert.That(!mapSystem.IsInitialized(mapId));
var testLocation = grid.Owner.ToCoordinates();
Assert.Multiple(() =>
@@ -184,7 +185,7 @@ public sealed class PrototypeSaveTest
IDependencyCollection dependencies, bool alwaysWrite = false,
ISerializationContext? context = null)
{
if (WritingComponent != "Transform" && (Prototype?.NoSpawn == false))
if (WritingComponent != "Transform" && Prototype?.HideSpawnMenu == false)
{
// Maybe this will be necessary in the future, but at the moment it just indicates that there is some
// issue, like a non-nullable entityUid data-field. If a component MUST have an entity uid to work with,

View File

@@ -29,7 +29,7 @@ public sealed class PullerTest
{
foreach (var proto in protoManager.EnumeratePrototypes<EntityPrototype>())
{
if (!proto.TryGetComponent(out PullerComponent? puller))
if (!proto.TryGetComponent(out PullerComponent? puller, compFactory))
continue;
if (!puller.NeedsHands)

View File

@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Linq;
using Content.Shared.Lathe;
using Content.Shared.Research.Prototypes;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests;
@@ -52,6 +53,7 @@ public sealed class ResearchTest
var server = pair.Server;
var protoManager = server.ResolveDependency<IPrototypeManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
await server.WaitAssertion(() =>
{
@@ -65,7 +67,7 @@ public sealed class ResearchTest
if (pair.IsTestPrototype(proto))
continue;
if (!proto.TryGetComponent<LatheComponent>(out var lathe))
if (!proto.TryGetComponent<LatheComponent>(out var lathe, compFact))
continue;
allLathes.Add(lathe);
}

View File

@@ -1,5 +1,4 @@
using System.Linq;
using Content.Server.Salvage;
using Content.Shared.CCVar;
using Content.Shared.Salvage;
using Robust.Server.GameObjects;
@@ -28,6 +27,7 @@ public sealed class SalvageTest
var mapManager = server.ResolveDependency<IMapManager>();
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
var cfg = server.ResolveDependency<IConfigurationManager>();
var mapSystem = entManager.System<SharedMapSystem>();
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
await server.WaitPost(() =>
@@ -36,7 +36,7 @@ public sealed class SalvageTest
{
var mapFile = salvage.MapPath;
var mapId = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId);
try
{
Assert.That(mapLoader.TryLoad(mapId, mapFile.ToString(), out var roots));

View File

@@ -23,6 +23,7 @@ namespace Content.IntegrationTests.Tests
var mapManager = server.ResolveDependency<IMapManager>();
var sEntities = server.ResolveDependency<IEntityManager>();
var mapLoader = sEntities.System<MapLoaderSystem>();
var mapSystem = sEntities.System<SharedMapSystem>();
var xformSystem = sEntities.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
var resManager = server.ResolveDependency<IResourceManager>();
var cfg = server.ResolveDependency<IConfigurationManager>();
@@ -33,19 +34,17 @@ namespace Content.IntegrationTests.Tests
var dir = new ResPath(mapPath).Directory;
resManager.UserData.CreateDir(dir);
var mapId = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId);
{
var mapGrid = mapManager.CreateGrid(mapId);
var mapGridEnt = mapGrid.Owner;
xformSystem.SetWorldPosition(mapGridEnt, new Vector2(10, 10));
mapGrid.SetTile(new Vector2i(0, 0), new Tile(1, (TileRenderFlag) 1, 255));
var mapGrid = mapManager.CreateGridEntity(mapId);
xformSystem.SetWorldPosition(mapGrid, new Vector2(10, 10));
mapSystem.SetTile(mapGrid, new Vector2i(0, 0), new Tile(1, (TileRenderFlag) 1, 255));
}
{
var mapGrid = mapManager.CreateGrid(mapId);
var mapGridEnt = mapGrid.Owner;
xformSystem.SetWorldPosition(mapGridEnt, new Vector2(-8, -8));
mapGrid.SetTile(new Vector2i(0, 0), new Tile(2, (TileRenderFlag) 1, 254));
var mapGrid = mapManager.CreateGridEntity(mapId);
xformSystem.SetWorldPosition(mapGrid, new Vector2(-8, -8));
mapSystem.SetTile(mapGrid, new Vector2i(0, 0), new Tile(2, (TileRenderFlag) 1, 254));
}
Assert.Multiple(() => mapLoader.SaveMap(mapId, mapPath));
@@ -74,7 +73,7 @@ namespace Content.IntegrationTests.Tests
Assert.Multiple(() =>
{
Assert.That(xformSystem.GetWorldPosition(gridXform), Is.EqualTo(new Vector2(10, 10)));
Assert.That(mapGrid.GetTileRef(new Vector2i(0, 0)).Tile, Is.EqualTo(new Tile(1, (TileRenderFlag) 1, 255)));
Assert.That(mapSystem.GetTileRef(gridUid, mapGrid, new Vector2i(0, 0)).Tile, Is.EqualTo(new Tile(1, (TileRenderFlag) 1, 255)));
});
}
{
@@ -88,7 +87,7 @@ namespace Content.IntegrationTests.Tests
Assert.Multiple(() =>
{
Assert.That(xformSystem.GetWorldPosition(gridXform), Is.EqualTo(new Vector2(-8, -8)));
Assert.That(mapGrid.GetTileRef(new Vector2i(0, 0)).Tile, Is.EqualTo(new Tile(2, (TileRenderFlag) 1, 254)));
Assert.That(mapSystem.GetTileRef(gridUid, mapGrid, new Vector2i(0, 0)).Tile, Is.EqualTo(new Tile(2, (TileRenderFlag) 1, 254)));
});
}
});

View File

@@ -25,17 +25,18 @@ namespace Content.IntegrationTests.Tests
var server = pair.Server;
var entManager = server.ResolveDependency<IEntityManager>();
var mapLoader = entManager.System<MapLoaderSystem>();
var mapSystem = entManager.System<SharedMapSystem>();
var mapManager = server.ResolveDependency<IMapManager>();
var cfg = server.ResolveDependency<IConfigurationManager>();
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
await server.WaitPost(() =>
{
var mapId0 = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId0);
// TODO: Properly find the "main" station grid.
var grid0 = mapManager.CreateGrid(mapId0);
var grid0 = mapManager.CreateGridEntity(mapId0);
mapLoader.Save(grid0.Owner, "save load save 1.yml");
var mapId1 = mapManager.CreateMap();
mapSystem.CreateMap(out var mapId1);
EntityUid grid1 = default!;
#pragma warning disable NUnit2045
Assert.That(mapLoader.TryLoad(mapId1, "save load save 1.yml", out var roots, new MapLoadOptions() { LoadMap = false }), $"Failed to load test map {TestMap}");
@@ -101,6 +102,7 @@ namespace Content.IntegrationTests.Tests
var server = pair.Server;
var mapLoader = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<MapLoaderSystem>();
var mapManager = server.ResolveDependency<IMapManager>();
var mapSystem = server.System<SharedMapSystem>();
MapId mapId = default;
var cfg = server.ResolveDependency<IConfigurationManager>();
@@ -109,8 +111,7 @@ namespace Content.IntegrationTests.Tests
// Load bagel.yml as uninitialized map, and save it to ensure it's up to date.
server.Post(() =>
{
mapId = mapManager.CreateMap();
mapManager.AddUninitializedMap(mapId);
mapSystem.CreateMap(out mapId, runMapInit: false);
mapManager.SetMapPaused(mapId, true);
Assert.That(mapLoader.TryLoad(mapId, TestMap, out _), $"Failed to load test map {TestMap}");
mapLoader.SaveMap(mapId, "load save ticks save 1.yml");
@@ -182,7 +183,8 @@ namespace Content.IntegrationTests.Tests
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var mapLoader = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<MapLoaderSystem>();
var mapLoader = server.System<MapLoaderSystem>();
var mapSystem = server.System<SharedMapSystem>();
var mapManager = server.ResolveDependency<IMapManager>();
var userData = server.ResolveDependency<IResourceManager>().UserData;
var cfg = server.ResolveDependency<IConfigurationManager>();
@@ -197,8 +199,7 @@ namespace Content.IntegrationTests.Tests
// Load & save the first map
server.Post(() =>
{
mapId = mapManager.CreateMap();
mapManager.AddUninitializedMap(mapId);
mapSystem.CreateMap(out mapId, runMapInit: false);
mapManager.SetMapPaused(mapId, true);
Assert.That(mapLoader.TryLoad(mapId, TestMap, out _), $"Failed to load test map {TestMap}");
mapLoader.SaveMap(mapId, fileA);
@@ -217,8 +218,7 @@ namespace Content.IntegrationTests.Tests
server.Post(() =>
{
mapManager.DeleteMap(mapId);
mapManager.CreateMap(mapId);
mapManager.AddUninitializedMap(mapId);
mapSystem.CreateMap(out mapId, runMapInit: false);
mapManager.SetMapPaused(mapId, true);
Assert.That(mapLoader.TryLoad(mapId, TestMap, out _), $"Failed to load test map {TestMap}");
mapLoader.SaveMap(mapId, fileB);

View File

@@ -24,7 +24,7 @@ public sealed partial class SerializationTest
Enum value = TestEnum.Bb;
var node = seriMan.WriteValue(value, notNullableOverride:true);
var node = seriMan.WriteValue(value, notNullableOverride: true);
var valueNode = node as ValueDataNode;
Assert.That(valueNode, Is.Not.Null);
@@ -34,22 +34,22 @@ public sealed partial class SerializationTest
var errors = seriMan.ValidateNode<Enum>(valueNode).GetErrors();
Assert.That(errors.Any(), Is.False);
var deserialized = seriMan.Read<Enum>(node, notNullableOverride:true);
var deserialized = seriMan.Read<Enum>(node, notNullableOverride: true);
Assert.That(deserialized, Is.EqualTo(value));
// Repeat test with enums in a data definitions.
var data = new TestData
{
Value = TestEnum.Cc,
Sequence = new() {TestEnum.Dd, TestEnum.Aa}
Sequence = [TestEnum.Dd, TestEnum.Aa]
};
node = seriMan.WriteValue(data, notNullableOverride:true);
node = seriMan.WriteValue(data, notNullableOverride: true);
errors = seriMan.ValidateNode<TestData>(node).GetErrors();
Assert.That(errors.Any(), Is.False);
var deserializedData = seriMan.Read<TestData>(node, notNullableOverride:false);
var deserializedData = seriMan.Read<TestData>(node, notNullableOverride: false);
Assert.That(deserializedData.Value, Is.EqualTo(data.Value));
Assert.That(deserializedData.Sequence.Count, Is.EqualTo(data.Sequence.Count));
@@ -60,7 +60,7 @@ public sealed partial class SerializationTest
Enum genericValue = TestEnum.Bb;
TestEnum typedValue = TestEnum.Bb;
var genericNode = seriMan.WriteValue(genericValue, notNullableOverride:true);
var genericNode = seriMan.WriteValue(genericValue, notNullableOverride: true);
var typedNode = seriMan.WriteValue(typedValue);
Assert.That(seriMan.ValidateNode<Enum>(genericNode).GetErrors().Any(), Is.False);
@@ -76,7 +76,7 @@ public sealed partial class SerializationTest
[DataDefinition]
private sealed partial class TestData
{
[DataField("value")] public Enum Value = default!;
[DataField("sequence")] public List<Enum> Sequence = default!;
[DataField] public Enum Value = default!;
[DataField] public List<Enum> Sequence = default!;
}
}

View File

@@ -2,7 +2,6 @@ using System.Numerics;
using Content.Server.Shuttles.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
@@ -23,33 +22,33 @@ namespace Content.IntegrationTests.Tests
var entManager = server.ResolveDependency<IEntityManager>();
var physicsSystem = entManager.System<SharedPhysicsSystem>();
EntityUid gridEnt = default;
PhysicsComponent gridPhys = null;
var map = await pair.CreateTestMap();
await server.WaitAssertion(() =>
{
var mapId = mapMan.CreateMap();
var grid = mapMan.CreateGridEntity(mapId);
gridEnt = grid.Owner;
var mapId = map.MapId;
var grid = map.Grid;
Assert.Multiple(() =>
{
Assert.That(entManager.HasComponent<ShuttleComponent>(gridEnt));
Assert.That(entManager.TryGetComponent(gridEnt, out gridPhys));
Assert.That(entManager.HasComponent<ShuttleComponent>(grid));
Assert.That(entManager.TryGetComponent(grid, out gridPhys));
});
Assert.Multiple(() =>
{
Assert.That(gridPhys.BodyType, Is.EqualTo(BodyType.Dynamic));
Assert.That(entManager.GetComponent<TransformComponent>(gridEnt).LocalPosition, Is.EqualTo(Vector2.Zero));
Assert.That(entManager.GetComponent<TransformComponent>(grid).LocalPosition, Is.EqualTo(Vector2.Zero));
});
physicsSystem.ApplyLinearImpulse(gridEnt, Vector2.One, body: gridPhys);
physicsSystem.ApplyLinearImpulse(grid, Vector2.One, body: gridPhys);
});
await server.WaitRunTicks(1);
await server.WaitAssertion(() =>
{
Assert.That(entManager.GetComponent<TransformComponent>(gridEnt).LocalPosition, Is.Not.EqualTo(Vector2.Zero));
Assert.That(entManager.GetComponent<TransformComponent>(map.Grid).LocalPosition, Is.Not.EqualTo(Vector2.Zero));
});
await pair.CleanReturnAsync();
}

View File

@@ -19,12 +19,12 @@ namespace Content.IntegrationTests.Tests.Sprite;
/// - Shouldn't have an item component
/// - Is missing the required sprite information.
/// If none of the abveo are true, it might need to be added to the list of ignored components, see
/// <see cref="_ignored"/>
/// <see cref="Ignored"/>
/// </remarks>
[TestFixture]
public sealed class PrototypeSaveTest
{
private static HashSet<string> _ignored = new()
private static readonly HashSet<string> Ignored = new()
{
// The only prototypes that should get ignored are those that REQUIRE setup to get a sprite. At that point it is
// the responsibility of the spawner to ensure that a valid sprite is set.
@@ -34,13 +34,13 @@ public sealed class PrototypeSaveTest
[Test]
public async Task AllItemsHaveSpritesTest()
{
var settings = new PoolSettings() {Connected = true}; // client needs to be in-game
var settings = new PoolSettings() { Connected = true }; // client needs to be in-game
await using var pair = await PoolManager.GetServerClient(settings);
List<EntityPrototype> badPrototypes = new();
List<EntityPrototype> badPrototypes = [];
await pair.Client.WaitPost(() =>
{
foreach (var proto in pair.GetPrototypesWithComponent<ItemComponent>(_ignored))
foreach (var proto in pair.GetPrototypesWithComponent<ItemComponent>(Ignored))
{
var dummy = pair.Client.EntMan.Spawn(proto.ID);
pair.Client.EntMan.RunMapInit(dummy, pair.Client.MetaData(dummy));

View File

@@ -36,16 +36,18 @@ public abstract class ToolshedTest : IInvocationContext
await TearDown();
}
protected virtual async Task TearDown()
protected virtual Task TearDown()
{
Assert.That(_expectedErrors, Is.Empty);
ClearErrors();
return Task.CompletedTask;
}
[SetUp]
public virtual async Task Setup()
{
Pair = await PoolManager.GetServerClient(new PoolSettings {Connected = Connected});
Pair = await PoolManager.GetServerClient(new PoolSettings { Connected = Connected });
Server = Pair.Server;
if (Connected)
@@ -142,7 +144,7 @@ public abstract class ToolshedTest : IInvocationContext
);
}
done:
done:
_errors.Add(err);
}

View File

@@ -111,6 +111,7 @@ namespace Content.IntegrationTests.Tests
await server.WaitIdleAsync();
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
await server.WaitAssertion(() =>
{
@@ -133,7 +134,7 @@ namespace Content.IntegrationTests.Tests
// Collect all the prototypes with StorageFills referencing those entities.
foreach (var proto in prototypeManager.EnumeratePrototypes<EntityPrototype>())
{
if (!proto.TryGetComponent<StorageFillComponent>(out var storage))
if (!proto.TryGetComponent<StorageFillComponent>(out var storage, compFact))
continue;
List<string> restockStore = new();

View File

@@ -1,10 +1,14 @@
using System.Text.Json;
using Content.Server.Administration.Managers;
using Robust.Server.Player;
namespace Content.Server.Administration.Logs.Converters;
[AdminLogConverter]
public sealed class EntityStringRepresentationConverter : AdminLogConverter<EntityStringRepresentation>
{
[Dependency] private readonly IAdminManager _adminManager = default!;
public override void Write(Utf8JsonWriter writer, EntityStringRepresentation value, JsonSerializerOptions options)
{
writer.WriteStartObject();
@@ -19,6 +23,21 @@ public sealed class EntityStringRepresentationConverter : AdminLogConverter<Enti
if (value.Session != null)
{
writer.WriteString("player", value.Session.UserId.UserId);
if (_adminManager.IsAdmin(value.Uid))
{
writer.WriteBoolean("admin", true);
}
}
if (value.Prototype != null)
{
writer.WriteString("prototype", value.Prototype);
}
if (value.Deleted)
{
writer.WriteBoolean("deleted", true);
}
writer.WriteEndObject();

View File

@@ -270,6 +270,9 @@ public sealed class AmeControllerSystem : EntitySystem
var humanReadableState = controller.Injecting ? "Inject" : "Not inject";
_adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to inject {controller.InjectionAmount} while set to {humanReadableState}");
/* This needs to be information which an admin is very likely to want to be informed about in order to be an admin alert or have a sound notification.
At the time of editing, players regularly "overclock" the AME and those cases require no admin attention.
// Admin alert
var safeLimit = 0;
if (TryGetAMENodeGroup(uid, out var group))
@@ -285,6 +288,7 @@ public sealed class AmeControllerSystem : EntitySystem
controller.EffectCooldown = _gameTiming.CurTime + controller.CooldownDuration;
}
}
*/
}
public void AdjustInjectionAmount(EntityUid uid, int delta, int min = 0, int max = int.MaxValue, EntityUid? user = null, AmeControllerComponent? controller = null)

View File

@@ -5,14 +5,22 @@ namespace Content.Server.Atmos.Piping.Other.Components
[RegisterComponent]
public sealed partial class GasMinerComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public bool Enabled { get; set; } = true;
public bool Broken { get; set; } = false;
[ViewVariables(VVAccess.ReadOnly)]
public bool Idle { get; set; } = false;
/// <summary>
/// If the number of moles in the external environment exceeds this number, no gas will be mined.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("maxExternalAmount")]
public float MaxExternalAmount { get; set; } = float.PositiveInfinity;
/// <summary>
/// If the pressure (in kPA) of the external environment exceeds this number, no gas will be mined.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("maxExternalPressure")]
public float MaxExternalPressure { get; set; } = Atmospherics.GasMinerDefaultMaxExternalPressure;

View File

@@ -25,10 +25,17 @@ namespace Content.Server.Atmos.Piping.Other.EntitySystems
{
var miner = ent.Comp;
if (!GetValidEnvironment(ent, out var environment))
{
miner.Idle = true;
return;
}
// SpawnAmount is declared in mol/s so to get the amount of gas we hope to mine, we have to multiply this by
// how long we have been waiting to spawn it and further cap the number according to the miner's state.
var toSpawn = CapSpawnAmount(ent, miner.SpawnAmount * args.dt, out var environment);
if (toSpawn <= 0f || environment == null || !miner.Enabled || !miner.SpawnGas.HasValue)
var toSpawn = CapSpawnAmount(ent, miner.SpawnAmount * args.dt, environment);
miner.Idle = toSpawn == 0;
if (miner.Idle || !miner.Enabled || !miner.SpawnGas.HasValue)
return;
// Time to mine some gas.
@@ -39,27 +46,26 @@ namespace Content.Server.Atmos.Piping.Other.EntitySystems
_atmosphereSystem.Merge(environment, merger);
}
private float CapSpawnAmount(Entity<GasMinerComponent> ent, float toSpawnTarget, [NotNullWhen(true)] out GasMixture? environment)
private bool GetValidEnvironment(Entity<GasMinerComponent> ent, [NotNullWhen(true)] out GasMixture? environment)
{
var (uid, miner) = ent;
var transform = Transform(uid);
environment = _atmosphereSystem.GetContainingMixture((uid, transform), true, true);
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
// Space.
// Treat space as an invalid environment
if (_atmosphereSystem.IsTileSpace(transform.GridUid, transform.MapUid, position))
{
miner.Broken = true;
return 0f;
environment = null;
return false;
}
// Air-blocked location.
if (environment == null)
{
miner.Broken = true;
return 0f;
}
environment = _atmosphereSystem.GetContainingMixture((uid, transform), true, true);
return environment != null;
}
private float CapSpawnAmount(Entity<GasMinerComponent> ent, float toSpawnTarget, GasMixture environment)
{
var (uid, miner) = ent;
// How many moles could we theoretically spawn. Cap by pressure and amount.
var allowableMoles = Math.Min(
@@ -69,11 +75,9 @@ namespace Content.Server.Atmos.Piping.Other.EntitySystems
var toSpawnReal = Math.Clamp(allowableMoles, 0f, toSpawnTarget);
if (toSpawnReal < Atmospherics.GasMinMoles) {
miner.Broken = true;
return 0f;
}
miner.Broken = false;
return toSpawnReal;
}
}

View File

@@ -1,40 +0,0 @@
using System.Linq;
using Content.Shared.BarSign;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.BarSign.Systems
{
public sealed class BarSignSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
public override void Initialize()
{
SubscribeLocalEvent<BarSignComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(EntityUid uid, BarSignComponent component, MapInitEvent args)
{
if (component.Current != null)
return;
var prototypes = _prototypeManager
.EnumeratePrototypes<BarSignPrototype>()
.Where(p => !p.Hidden)
.ToList();
var newPrototype = _random.Pick(prototypes);
var meta = Comp<MetaDataComponent>(uid);
var name = newPrototype.Name != string.Empty ? newPrototype.Name : "barsign-component-name";
_metaData.SetEntityName(uid, Loc.GetString(name), meta);
_metaData.SetEntityDescription(uid, Loc.GetString(newPrototype.Description), meta);
component.Current = newPrototype.ID;
Dirty(uid, component);
}
}
}

View File

@@ -30,10 +30,18 @@ public sealed class AntagLoadProfileRuleSystem : GameRuleSystem<AntagLoadProfile
var profile = args.Session != null
? _prefs.GetPreferences(args.Session.UserId).SelectedCharacter as HumanoidCharacterProfile
: HumanoidCharacterProfile.RandomWithSpecies();
if (profile?.Species is not {} speciesId || !_proto.TryIndex<SpeciesPrototype>(speciesId, out var species))
SpeciesPrototype? species;
if (ent.Comp.SpeciesOverride != null)
{
species = _proto.Index(ent.Comp.SpeciesOverride.Value);
}
else if (profile?.Species is not { } speciesId || !_proto.TryIndex(speciesId, out species))
{
species = _proto.Index<SpeciesPrototype>(SharedHumanoidAppearanceSystem.DefaultSpecies);
}
args.Entity = Spawn(species.Prototype);
_humanoid.LoadProfile(args.Entity.Value, profile);
_humanoid.LoadProfile(args.Entity.Value, profile?.WithSpecies(species.ID));
}
}

View File

@@ -1,7 +1,17 @@
using Content.Shared.Humanoid.Prototypes;
using Robust.Shared.Prototypes;
namespace Content.Server.GameTicking.Rules.Components;
/// <summary>
/// Makes this rules antags spawn a humanoid, either from the player's profile or a random one.
/// </summary>
[RegisterComponent]
public sealed partial class AntagLoadProfileRuleComponent : Component;
public sealed partial class AntagLoadProfileRuleComponent : Component
{
/// <summary>
/// If specified, the profile loaded will be made into this species.
/// </summary>
[DataField]
public ProtoId<SpeciesPrototype>? SpeciesOverride;
}

View File

@@ -57,13 +57,12 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
SubscribeLocalEvent<NukeOperativeComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<NukeOperativeComponent, EntityZombifiedEvent>(OnOperativeZombified);
SubscribeLocalEvent<NukeOpsShuttleComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<ConsoleFTLAttemptEvent>(OnShuttleFTLAttempt);
SubscribeLocalEvent<WarDeclaredEvent>(OnWarDeclared);
SubscribeLocalEvent<CommunicationConsoleCallShuttleAttemptEvent>(OnShuttleCallAttempt);
SubscribeLocalEvent<NukeopsRuleComponent, AfterAntagEntitySelectedEvent>(OnAfterAntagEntSelected);
SubscribeLocalEvent<NukeopsRuleComponent, RuleLoadedGridsEvent>(OnRuleLoadedGrids);
}
protected override void Started(EntityUid uid, NukeopsRuleComponent component, GameRuleComponent gameRule,
@@ -256,17 +255,18 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
RemCompDeferred(uid, component);
}
private void OnMapInit(Entity<NukeOpsShuttleComponent> ent, ref MapInitEvent args)
private void OnRuleLoadedGrids(Entity<NukeopsRuleComponent> ent, ref RuleLoadedGridsEvent args)
{
var map = Transform(ent).MapID;
var rules = EntityQueryEnumerator<NukeopsRuleComponent, RuleGridsComponent>();
while (rules.MoveNext(out var uid, out _, out var grids))
// Check each nukie shuttle
var query = EntityQueryEnumerator<NukeOpsShuttleComponent>();
while (query.MoveNext(out var uid, out var shuttle))
{
if (map != grids.Map)
continue;
ent.Comp.AssociatedRule = uid;
break;
// Check if the shuttle's mapID is the one that just got loaded for this rule
if (Transform(uid).MapID == args.Map)
{
shuttle.AssociatedRule = ent;
break;
}
}
}
@@ -376,7 +376,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
if (Transform(uid).MapID != Transform(outpost).MapID) // Will receive bonus TC only on their start outpost
continue;
_store.TryAddCurrency(new () { { TelecrystalCurrencyPrototype, nukieRule.Comp.WarTcAmountPerNukie } }, uid, component);
_store.TryAddCurrency(new() { { TelecrystalCurrencyPrototype, nukieRule.Comp.WarTcAmountPerNukie } }, uid, component);
var msg = Loc.GetString("store-currency-war-boost-given", ("target", uid));
_popupSystem.PopupEntity(msg, uid);

View File

@@ -7,7 +7,7 @@ using Robust.Shared.Console;
namespace Content.Server.Ghost
{
[AnyCommand]
public sealed class Ghost : IConsoleCommand
public sealed class GhostCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entities = default!;

View File

@@ -0,0 +1,7 @@
namespace Content.Server.IgnitionSource;
/// <summary>
/// Raised in order to toggle the ignitionSourceComponent on an entity on or off
/// </summary>
[ByRefEvent]
public readonly record struct IgnitionEvent(bool Ignite = false);

View File

@@ -19,18 +19,25 @@ public sealed class IgnitionSourceSystem : EntitySystem
SubscribeLocalEvent<IgnitionSourceComponent, IsHotEvent>(OnIsHot);
SubscribeLocalEvent<ItemToggleHotComponent, ItemToggledEvent>(OnItemToggle);
SubscribeLocalEvent<IgnitionSourceComponent, IgnitionEvent>(OnIgnitionEvent);
}
private void OnIsHot(Entity<IgnitionSourceComponent> ent, ref IsHotEvent args)
{
SetIgnited((ent.Owner, ent.Comp), args.IsHot);
args.IsHot = ent.Comp.Ignited;
}
private void OnItemToggle(Entity<ItemToggleHotComponent> ent, ref ItemToggledEvent args)
{
if (TryComp<IgnitionSourceComponent>(ent, out var comp))
SetIgnited((ent.Owner, comp), args.Activated);
}
private void OnIgnitionEvent(Entity<IgnitionSourceComponent> ent, ref IgnitionEvent args)
{
SetIgnited((ent.Owner, ent.Comp), args.Ignite);
}
/// <summary>
/// Simply sets the ignited field to the ignited param.
/// </summary>

View File

@@ -1,3 +1,4 @@
using Content.Server.IgnitionSource;
using Content.Server.Light.Components;
using Content.Shared.Clothing.Components;
using Content.Shared.Clothing.EntitySystems;
@@ -99,8 +100,8 @@ namespace Content.Server.Light.EntitySystems
_item.SetHeldPrefix(ent, "lit", component: item);
}
var isHotEvent = new IsHotEvent() {IsHot = true};
RaiseLocalEvent(ent, isHotEvent);
var ignite = new IgnitionEvent(true);
RaiseLocalEvent(ent, ref ignite);
component.CurrentState = ExpendableLightState.Lit;
component.StateExpiryTime = component.GlowDuration;
@@ -134,8 +135,8 @@ namespace Content.Server.Light.EntitySystems
case ExpendableLightState.Dead:
_appearance.SetData(ent, ExpendableLightVisuals.Behavior, string.Empty, appearance);
var isHotEvent = new IsHotEvent() {IsHot = true};
RaiseLocalEvent(ent, isHotEvent);
var ignite = new IgnitionEvent(false);
RaiseLocalEvent(ent, ref ignite);
break;
}
}

View File

@@ -0,0 +1,123 @@
namespace Content.Server.NPC.Pathfinding;
public sealed partial class PathfindingSystem
{
/*
* Handle BFS searches from Start->End. Doesn't consider NPC pathfinding.
*/
/// <summary>
/// Pathfinding args for a 1-many path.
/// </summary>
public record struct BreadthPathArgs()
{
public Vector2i Start;
public List<Vector2i> Ends;
public bool Diagonals = false;
public Func<Vector2i, float>? TileCost;
public int Limit = 10000;
}
/// <summary>
/// Gets a BFS path from start to any end. Can also supply an optional tile-cost for tiles.
/// </summary>
public SimplePathResult GetBreadthPath(BreadthPathArgs args)
{
var cameFrom = new Dictionary<Vector2i, Vector2i>();
var costSoFar = new Dictionary<Vector2i, float>();
var frontier = new PriorityQueue<Vector2i, float>();
costSoFar[args.Start] = 0f;
frontier.Enqueue(args.Start, 0f);
var count = 0;
while (frontier.TryDequeue(out var node, out _) && count < args.Limit)
{
count++;
if (args.Ends.Contains(node))
{
// Found target
var path = ReconstructPath(node, cameFrom);
return new SimplePathResult()
{
CameFrom = cameFrom,
Path = path,
};
}
var gCost = costSoFar[node];
if (args.Diagonals)
{
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
var neighbor = node + new Vector2i(x, y);
var neighborCost = OctileDistance(node, neighbor) * args.TileCost?.Invoke(neighbor) ?? 1f;
if (neighborCost.Equals(0f))
{
continue;
}
// f = g + h
// gScore is distance to the start node
// hScore is distance to the end node
var gScore = gCost + neighborCost;
// Slower to get here so just ignore it.
if (costSoFar.TryGetValue(neighbor, out var nextValue) && gScore >= nextValue)
{
continue;
}
cameFrom[neighbor] = node;
costSoFar[neighbor] = gScore;
// pFactor is tie-breaker where the fscore is otherwise equal.
// See http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#breaking-ties
// There's other ways to do it but future consideration
// The closer the fScore is to the actual distance then the better the pathfinder will be
// (i.e. somewhere between 1 and infinite)
// Can use hierarchical pathfinder or whatever to improve the heuristic but this is fine for now.
frontier.Enqueue(neighbor, gScore);
}
}
}
else
{
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
if (x != 0 && y != 0)
continue;
var neighbor = node + new Vector2i(x, y);
var neighborCost = ManhattanDistance(node, neighbor) * args.TileCost?.Invoke(neighbor) ?? 1f;
if (neighborCost.Equals(0f))
continue;
var gScore = gCost + neighborCost;
if (costSoFar.TryGetValue(neighbor, out var nextValue) && gScore >= nextValue)
continue;
cameFrom[neighbor] = node;
costSoFar[neighbor] = gScore;
frontier.Enqueue(neighbor, gScore);
}
}
}
}
return SimplePathResult.NoPath;
}
}

View File

@@ -0,0 +1,74 @@
namespace Content.Server.NPC.Pathfinding;
public sealed partial class PathfindingSystem
{
public void GridCast(Vector2i start, Vector2i end, Vector2iCallback callback)
{
// https://gist.github.com/Pyr3z/46884d67641094d6cf353358566db566
// declare all locals at the top so it's obvious how big the footprint is
int dx, dy, xinc, yinc, side, i, error;
// starting cell is always returned
if (!callback(start))
return;
xinc = (end.X < start.X) ? -1 : 1;
yinc = (end.Y < start.Y) ? -1 : 1;
dx = xinc * (end.X - start.X);
dy = yinc * (end.Y - start.Y);
var ax = start.X;
var ay = start.Y;
if (dx == dy) // Handle perfect diagonals
{
// I include this "optimization" for more aesthetic reasons, actually.
// While Bresenham's Line can handle perfect diagonals just fine, it adds
// additional cells to the line that make it not a perfect diagonal
// anymore. So, while this branch is ~twice as fast as the next branch,
// the real reason it is here is for style.
// Also, there *is* the reason of performance. If used for cell-based
// raycasts, for example, then perfect diagonals will check half as many
// cells.
while (dx --> 0)
{
ax += xinc;
ay += yinc;
if (!callback(new Vector2i(ax, ay)))
return;
}
return;
}
// Handle all other lines
side = -1 * ((dx == 0 ? yinc : xinc) - 1);
i = dx + dy;
error = dx - dy;
dx *= 2;
dy *= 2;
while (i --> 0)
{
if (error > 0 || error == side)
{
ax += xinc;
error -= dy;
}
else
{
ay += yinc;
error += dx;
}
if (!callback(new Vector2i(ax, ay)))
return;
}
}
public delegate bool Vector2iCallback(Vector2i index);
}

View File

@@ -0,0 +1,154 @@
namespace Content.Server.NPC.Pathfinding;
public sealed partial class PathfindingSystem
{
/// <summary>
/// Pathfinding args for a 1-1 path.
/// </summary>
public record struct SimplePathArgs()
{
public Vector2i Start;
public Vector2i End;
public bool Diagonals = false;
public int Limit = 10000;
/// <summary>
/// Custom tile-costs if applicable.
/// </summary>
public Func<Vector2i, float>? TileCost;
}
public record struct SimplePathResult
{
public static SimplePathResult NoPath = new();
public List<Vector2i> Path;
public Dictionary<Vector2i, Vector2i> CameFrom;
}
/// <summary>
/// Gets simple A* path from start to end. Can also supply an optional tile-cost for tiles.
/// </summary>
public SimplePathResult GetPath(SimplePathArgs args)
{
var cameFrom = new Dictionary<Vector2i, Vector2i>();
var costSoFar = new Dictionary<Vector2i, float>();
var frontier = new PriorityQueue<Vector2i, float>();
costSoFar[args.Start] = 0f;
frontier.Enqueue(args.Start, 0f);
var count = 0;
while (frontier.TryDequeue(out var node, out _) && count < args.Limit)
{
count++;
if (node == args.End)
{
// Found target
var path = ReconstructPath(args.End, cameFrom);
return new SimplePathResult()
{
CameFrom = cameFrom,
Path = path,
};
}
var gCost = costSoFar[node];
if (args.Diagonals)
{
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
var neighbor = node + new Vector2i(x, y);
var neighborCost = OctileDistance(node, neighbor) * args.TileCost?.Invoke(neighbor) ?? 1f;
if (neighborCost.Equals(0f))
{
continue;
}
// f = g + h
// gScore is distance to the start node
// hScore is distance to the end node
var gScore = gCost + neighborCost;
// Slower to get here so just ignore it.
if (costSoFar.TryGetValue(neighbor, out var nextValue) && gScore >= nextValue)
{
continue;
}
cameFrom[neighbor] = node;
costSoFar[neighbor] = gScore;
// pFactor is tie-breaker where the fscore is otherwise equal.
// See http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#breaking-ties
// There's other ways to do it but future consideration
// The closer the fScore is to the actual distance then the better the pathfinder will be
// (i.e. somewhere between 1 and infinite)
// Can use hierarchical pathfinder or whatever to improve the heuristic but this is fine for now.
var hScore = OctileDistance(args.End, neighbor) * (1.0f + 1.0f / 1000.0f);
var fScore = gScore + hScore;
frontier.Enqueue(neighbor, fScore);
}
}
}
else
{
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
if (x != 0 && y != 0)
continue;
var neighbor = node + new Vector2i(x, y);
var neighborCost = ManhattanDistance(node, neighbor) * args.TileCost?.Invoke(neighbor) ?? 1f;
if (neighborCost.Equals(0f))
continue;
var gScore = gCost + neighborCost;
if (costSoFar.TryGetValue(neighbor, out var nextValue) && gScore >= nextValue)
continue;
cameFrom[neighbor] = node;
costSoFar[neighbor] = gScore;
// Still use octile even for manhattan distance.
var hScore = OctileDistance(args.End, neighbor) * 1.001f;
var fScore = gScore + hScore;
frontier.Enqueue(neighbor, fScore);
}
}
}
}
return SimplePathResult.NoPath;
}
private List<Vector2i> ReconstructPath(Vector2i end, Dictionary<Vector2i, Vector2i> cameFrom)
{
var path = new List<Vector2i>()
{
end,
};
var node = end;
while (cameFrom.TryGetValue(node, out var source))
{
path.Add(source);
node = source;
}
path.Reverse();
return path;
}
}

View File

@@ -0,0 +1,180 @@
using Robust.Shared.Collections;
using Robust.Shared.Random;
namespace Content.Server.NPC.Pathfinding;
public sealed partial class PathfindingSystem
{
public record struct SimplifyPathArgs
{
public Vector2i Start;
public Vector2i End;
public List<Vector2i> Path;
}
public record struct SplinePathResult()
{
public static SplinePathResult NoPath = new();
public List<Vector2i> Points = new();
public List<Vector2i> Path = new();
public Dictionary<Vector2i, Vector2i> CameFrom;
}
public record struct SplinePathArgs(SimplePathArgs Args)
{
public SimplePathArgs Args = Args;
public float MaxRatio = 0.25f;
/// <summary>
/// Minimum distance between subdivisions.
/// </summary>
public int Distance = 20;
}
/// <summary>
/// Gets a spline path from start to end.
/// </summary>
public SplinePathResult GetSplinePath(SplinePathArgs args, Random random)
{
var start = args.Args.Start;
var end = args.Args.End;
var path = new List<Vector2i>();
var pairs = new ValueList<(Vector2i Start, Vector2i End)> { (start, end) };
var subdivided = true;
// Sub-divide recursively
while (subdivided)
{
// Sometimes we might inadvertantly get 2 nodes too close together so better to just check each one as it comes up instead.
var i = 0;
subdivided = false;
while (i < pairs.Count)
{
var pointA = pairs[i].Start;
var pointB = pairs[i].End;
var vector = pointB - pointA;
var halfway = vector / 2f;
// Finding the point
var adj = halfway.Length();
// Should we even subdivide.
if (adj <= args.Distance)
{
// Just check the next entry no double skip.
i++;
continue;
}
subdivided = true;
var opposite = args.MaxRatio * adj;
var hypotenuse = MathF.Sqrt(MathF.Pow(adj, 2) + MathF.Pow(opposite, 2));
// Okay so essentially we have 2 points and no poly
// We add 2 other points to form a diamond and want some point halfway between randomly offset.
var angle = new Angle(MathF.Atan(opposite / adj));
var pointAPerp = pointA + angle.RotateVec(halfway).Normalized() * hypotenuse;
var pointBPerp = pointA + (-angle).RotateVec(halfway).Normalized() * hypotenuse;
var perpLine = pointBPerp - pointAPerp;
var perpHalfway = perpLine.Length() / 2f;
var splinePoint = (pointAPerp + perpLine.Normalized() * random.NextFloat(-args.MaxRatio, args.MaxRatio) * perpHalfway).Floored();
// We essentially take (A, B) and turn it into (A, C) & (C, B)
pairs[i] = (pointA, splinePoint);
pairs.Insert(i + 1, (splinePoint, pointB));
i+= 2;
}
}
var spline = new ValueList<Vector2i>(pairs.Count - 1)
{
start
};
foreach (var pair in pairs)
{
spline.Add(pair.End);
}
// Now we need to pathfind between each node on the spline.
// TODO: Add rotation version or straight-line version for pathfinder config
// Move the worm pathfinder to here I think.
var cameFrom = new Dictionary<Vector2i, Vector2i>();
// TODO: Need to get rid of the branch bullshit.
var points = new List<Vector2i>();
for (var i = 0; i < spline.Count - 1; i++)
{
var point = spline[i];
var target = spline[i + 1];
points.Add(point);
var aStarArgs = args.Args with { Start = point, End = target };
var aStarResult = GetPath(aStarArgs);
if (aStarResult == SimplePathResult.NoPath)
return SplinePathResult.NoPath;
path.AddRange(aStarResult.Path[0..]);
foreach (var a in aStarResult.CameFrom)
{
cameFrom[a.Key] = a.Value;
}
}
points.Add(spline[^1]);
var simple = SimplifyPath(new SimplifyPathArgs()
{
Start = args.Args.Start,
End = args.Args.End,
Path = path,
});
return new SplinePathResult()
{
Path = simple,
CameFrom = cameFrom,
Points = points,
};
}
/// <summary>
/// Does a simpler pathfinder over the nodes to prune unnecessary branches.
/// </summary>
public List<Vector2i> SimplifyPath(SimplifyPathArgs args)
{
var nodes = new HashSet<Vector2i>(args.Path);
var result = GetBreadthPath(new BreadthPathArgs()
{
Start = args.Start,
Ends = new List<Vector2i>()
{
args.End,
},
TileCost = node =>
{
if (!nodes.Contains(node))
return 0f;
return 1f;
}
});
return result.Path;
}
}

View File

@@ -0,0 +1,89 @@
using System.Numerics;
using Robust.Shared.Random;
namespace Content.Server.NPC.Pathfinding;
public sealed partial class PathfindingSystem
{
/// <summary>
/// Widens the path by the specified amount.
/// </summary>
public HashSet<Vector2i> GetWiden(WidenArgs args, Random random)
{
var tiles = new HashSet<Vector2i>(args.Path.Count * 2);
var variance = (args.MaxWiden - args.MinWiden) / 2f + args.MinWiden;
var counter = 0;
foreach (var tile in args.Path)
{
counter++;
if (counter != args.TileSkip)
continue;
counter = 0;
var center = new Vector2(tile.X + 0.5f, tile.Y + 0.5f);
if (args.Square)
{
for (var x = -variance; x <= variance; x++)
{
for (var y = -variance; y <= variance; y++)
{
var neighbor = center + new Vector2(x, y);
tiles.Add(neighbor.Floored());
}
}
}
else
{
for (var x = -variance; x <= variance; x++)
{
for (var y = -variance; y <= variance; y++)
{
var offset = new Vector2(x, y);
if (offset.Length() > variance)
continue;
var neighbor = center + offset;
tiles.Add(neighbor.Floored());
}
}
}
variance += random.NextFloat(-args.Variance * args.TileSkip, args.Variance * args.TileSkip);
variance = Math.Clamp(variance, args.MinWiden, args.MaxWiden);
}
return tiles;
}
public record struct WidenArgs()
{
public bool Square = false;
/// <summary>
/// How many tiles to skip between iterations., 1-in-n
/// </summary>
public int TileSkip = 3;
/// <summary>
/// Maximum amount to vary per tile.
/// </summary>
public float Variance = 0.25f;
/// <summary>
/// Minimum width.
/// </summary>
public float MinWiden = 2f;
public float MaxWiden = 7f;
public List<Vector2i> Path;
}
}

View File

@@ -142,6 +142,13 @@ public sealed partial class NPCSteeringSystem
// Grab the target position, either the next path node or our end goal..
var targetCoordinates = GetTargetCoordinates(steering);
if (!targetCoordinates.IsValid(EntityManager))
{
steering.Status = SteeringStatus.NoPath;
return false;
}
var needsPath = false;
// If the next node is invalid then get new ones
@@ -243,6 +250,14 @@ public sealed partial class NPCSteeringSystem
// Alright just adjust slightly and grab the next node so we don't stop moving for a tick.
// TODO: If it's the last node just grab the target instead.
targetCoordinates = GetTargetCoordinates(steering);
if (!targetCoordinates.IsValid(EntityManager))
{
SetDirection(mover, steering, Vector2.Zero);
steering.Status = SteeringStatus.NoPath;
return false;
}
targetMap = targetCoordinates.ToMap(EntityManager, _transform);
// Can't make it again.

View File

@@ -810,7 +810,7 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
// At least for now unless we do lookups or smth, only work with anchoring.
if (_xformQuery.TryGetComponent(ent, out var xform) && !xform.Anchored)
{
_transform.AnchorEntity(ent, xform, gridUid, grid, indices);
_transform.AnchorEntity((ent, xform), (gridUid, grid), indices);
}
loadedEntities.Add(ent, indices);

File diff suppressed because it is too large Load Diff

View File

@@ -1,138 +0,0 @@
using System.Threading.Tasks;
using Content.Server.Parallax;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Parallax.Biomes.Markers;
using Content.Shared.Procedural;
using Content.Shared.Procedural.PostGeneration;
using Content.Shared.Random.Helpers;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Utility;
namespace Content.Server.Procedural;
public sealed partial class DungeonJob
{
/*
* Handles PostGen code for marker layers + biomes.
*/
private async Task PostGen(BiomePostGen postGen, Dungeon dungeon, EntityUid gridUid, MapGridComponent grid, Random random)
{
if (_entManager.TryGetComponent(gridUid, out BiomeComponent? biomeComp))
return;
biomeComp = _entManager.AddComponent<BiomeComponent>(gridUid);
var biomeSystem = _entManager.System<BiomeSystem>();
biomeSystem.SetTemplate(gridUid, biomeComp, _prototype.Index(postGen.BiomeTemplate));
var seed = random.Next();
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
foreach (var node in dungeon.RoomTiles)
{
// Need to set per-tile to override data.
if (biomeSystem.TryGetTile(node, biomeComp.Layers, seed, grid, out var tile))
{
_maps.SetTile(gridUid, grid, node, tile.Value);
}
if (biomeSystem.TryGetDecals(node, biomeComp.Layers, seed, grid, out var decals))
{
foreach (var decal in decals)
{
_decals.TryAddDecal(decal.ID, new EntityCoordinates(gridUid, decal.Position), out _);
}
}
if (biomeSystem.TryGetEntity(node, biomeComp, grid, out var entityProto))
{
var ent = _entManager.SpawnEntity(entityProto, new EntityCoordinates(gridUid, node + grid.TileSizeHalfVector));
var xform = xformQuery.Get(ent);
if (!xform.Comp.Anchored)
{
_transform.AnchorEntity(ent, xform);
}
// TODO: Engine bug with SpawnAtPosition
DebugTools.Assert(xform.Comp.Anchored);
}
await SuspendIfOutOfTime();
ValidateResume();
}
biomeComp.Enabled = false;
}
private async Task PostGen(BiomeMarkerLayerPostGen postGen, Dungeon dungeon, EntityUid gridUid, MapGridComponent grid, Random random)
{
if (!_entManager.TryGetComponent(gridUid, out BiomeComponent? biomeComp))
return;
var biomeSystem = _entManager.System<BiomeSystem>();
var weightedRandom = _prototype.Index(postGen.MarkerTemplate);
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
var templates = new Dictionary<string, int>();
for (var i = 0; i < postGen.Count; i++)
{
var template = weightedRandom.Pick(random);
var count = templates.GetOrNew(template);
count++;
templates[template] = count;
}
foreach (var (template, count) in templates)
{
var markerTemplate = _prototype.Index<BiomeMarkerLayerPrototype>(template);
var bounds = new Box2i();
foreach (var tile in dungeon.RoomTiles)
{
bounds = bounds.UnionTile(tile);
}
await SuspendIfOutOfTime();
ValidateResume();
biomeSystem.GetMarkerNodes(gridUid, biomeComp, grid, markerTemplate, true, bounds, count,
random, out var spawnSet, out var existing, false);
await SuspendIfOutOfTime();
ValidateResume();
foreach (var ent in existing)
{
_entManager.DeleteEntity(ent);
}
await SuspendIfOutOfTime();
ValidateResume();
foreach (var (node, mask) in spawnSet)
{
string? proto;
if (mask != null && markerTemplate.EntityMask.TryGetValue(mask, out var maskedProto))
{
proto = maskedProto;
}
else
{
proto = markerTemplate.Prototype;
}
var ent = _entManager.SpawnAtPosition(proto, new EntityCoordinates(gridUid, node + grid.TileSizeHalfVector));
var xform = xformQuery.Get(ent);
if (!xform.Comp.Anchored)
_transform.AnchorEntity(ent, xform);
await SuspendIfOutOfTime();
ValidateResume();
}
}
}
}

View File

@@ -1,192 +0,0 @@
using System.Threading;
using System.Threading.Tasks;
using Content.Server.Construction;
using Robust.Shared.CPUJob.JobQueues;
using Content.Server.Decals;
using Content.Shared.Construction.EntitySystems;
using Content.Shared.Maps;
using Content.Shared.Procedural;
using Content.Shared.Procedural.DungeonGenerators;
using Content.Shared.Procedural.PostGeneration;
using Content.Shared.Tag;
using Robust.Server.Physics;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Server.Procedural;
public sealed partial class DungeonJob : Job<Dungeon>
{
private readonly IEntityManager _entManager;
private readonly IMapManager _mapManager;
private readonly IPrototypeManager _prototype;
private readonly ITileDefinitionManager _tileDefManager;
private readonly AnchorableSystem _anchorable;
private readonly DecalSystem _decals;
private readonly DungeonSystem _dungeon;
private readonly EntityLookupSystem _lookup;
private readonly TagSystem _tag;
private readonly TileSystem _tile;
private readonly SharedMapSystem _maps;
private readonly SharedTransformSystem _transform;
private readonly DungeonConfigPrototype _gen;
private readonly int _seed;
private readonly Vector2i _position;
private readonly MapGridComponent _grid;
private readonly EntityUid _gridUid;
private readonly ISawmill _sawmill;
public DungeonJob(
ISawmill sawmill,
double maxTime,
IEntityManager entManager,
IMapManager mapManager,
IPrototypeManager prototype,
ITileDefinitionManager tileDefManager,
AnchorableSystem anchorable,
DecalSystem decals,
DungeonSystem dungeon,
EntityLookupSystem lookup,
TagSystem tag,
TileSystem tile,
SharedTransformSystem transform,
DungeonConfigPrototype gen,
MapGridComponent grid,
EntityUid gridUid,
int seed,
Vector2i position,
CancellationToken cancellation = default) : base(maxTime, cancellation)
{
_sawmill = sawmill;
_entManager = entManager;
_mapManager = mapManager;
_prototype = prototype;
_tileDefManager = tileDefManager;
_anchorable = anchorable;
_decals = decals;
_dungeon = dungeon;
_lookup = lookup;
_tag = tag;
_tile = tile;
_maps = _entManager.System<SharedMapSystem>();
_transform = transform;
_gen = gen;
_grid = grid;
_gridUid = gridUid;
_seed = seed;
_position = position;
}
protected override async Task<Dungeon?> Process()
{
Dungeon dungeon;
_sawmill.Info($"Generating dungeon {_gen.ID} with seed {_seed} on {_entManager.ToPrettyString(_gridUid)}");
_grid.CanSplit = false;
switch (_gen.Generator)
{
case NoiseDunGen noise:
dungeon = await GenerateNoiseDungeon(noise, _gridUid, _grid, _seed);
break;
case PrefabDunGen prefab:
dungeon = await GeneratePrefabDungeon(prefab, _gridUid, _grid, _seed);
DebugTools.Assert(dungeon.RoomExteriorTiles.Count > 0);
break;
default:
throw new NotImplementedException();
}
DebugTools.Assert(dungeon.RoomTiles.Count > 0);
// To make it slightly more deterministic treat this RNG as separate ig.
var random = new Random(_seed);
foreach (var post in _gen.PostGeneration)
{
_sawmill.Debug($"Doing postgen {post.GetType()} for {_gen.ID} with seed {_seed}");
switch (post)
{
case AutoCablingPostGen cabling:
await PostGen(cabling, dungeon, _gridUid, _grid, random);
break;
case BiomePostGen biome:
await PostGen(biome, dungeon, _gridUid, _grid, random);
break;
case BoundaryWallPostGen boundary:
await PostGen(boundary, dungeon, _gridUid, _grid, random);
break;
case CornerClutterPostGen clutter:
await PostGen(clutter, dungeon, _gridUid, _grid, random);
break;
case CorridorClutterPostGen corClutter:
await PostGen(corClutter, dungeon, _gridUid, _grid, random);
break;
case CorridorPostGen cordor:
await PostGen(cordor, dungeon, _gridUid, _grid, random);
break;
case CorridorDecalSkirtingPostGen decks:
await PostGen(decks, dungeon, _gridUid, _grid, random);
break;
case EntranceFlankPostGen flank:
await PostGen(flank, dungeon, _gridUid, _grid, random);
break;
case JunctionPostGen junc:
await PostGen(junc, dungeon, _gridUid, _grid, random);
break;
case MiddleConnectionPostGen dordor:
await PostGen(dordor, dungeon, _gridUid, _grid, random);
break;
case DungeonEntrancePostGen entrance:
await PostGen(entrance, dungeon, _gridUid, _grid, random);
break;
case ExternalWindowPostGen externalWindow:
await PostGen(externalWindow, dungeon, _gridUid, _grid, random);
break;
case InternalWindowPostGen internalWindow:
await PostGen(internalWindow, dungeon, _gridUid, _grid, random);
break;
case BiomeMarkerLayerPostGen markerPost:
await PostGen(markerPost, dungeon, _gridUid, _grid, random);
break;
case RoomEntrancePostGen rEntrance:
await PostGen(rEntrance, dungeon, _gridUid, _grid, random);
break;
case WallMountPostGen wall:
await PostGen(wall, dungeon, _gridUid, _grid, random);
break;
case WormCorridorPostGen worm:
await PostGen(worm, dungeon, _gridUid, _grid, random);
break;
default:
throw new NotImplementedException();
}
await SuspendIfOutOfTime();
if (!ValidateResume())
break;
}
// Defer splitting so they don't get spammed and so we don't have to worry about tracking the grid along the way.
_grid.CanSplit = true;
_entManager.System<GridFixtureSystem>().CheckSplits(_gridUid);
return dungeon;
}
private bool ValidateResume()
{
if (_entManager.Deleted(_gridUid))
return false;
return true;
}
}

View File

@@ -0,0 +1,58 @@
using System.Threading.Tasks;
using Content.Server.NPC.Pathfinding;
using Content.Shared.Maps;
using Content.Shared.Procedural;
using Content.Shared.Procedural.DungeonGenerators;
using Robust.Shared.Collections;
using Robust.Shared.Random;
using Robust.Shared.Utility;
namespace Content.Server.Procedural.DungeonJob;
public sealed partial class DungeonJob
{
/// <summary>
/// <see cref="ExteriorDunGen"/>
/// </summary>
private async Task<List<Dungeon>> GenerateExteriorDungen(Vector2i position, ExteriorDunGen dungen, HashSet<Vector2i> reservedTiles, Random random)
{
DebugTools.Assert(_grid.ChunkCount > 0);
var aabb = new Box2i(_grid.LocalAABB.BottomLeft.Floored(), _grid.LocalAABB.TopRight.Floored());
var angle = random.NextAngle();
var distance = Math.Max(aabb.Width / 2f + 1f, aabb.Height / 2f + 1f);
var startTile = new Vector2i(0, (int) distance).Rotate(angle);
Vector2i? dungeonSpawn = null;
var pathfinder = _entManager.System<PathfindingSystem>();
// Gridcast
pathfinder.GridCast(startTile, position, tile =>
{
if (!_maps.TryGetTileRef(_gridUid, _grid, tile, out var tileRef) ||
tileRef.Tile.IsSpace(_tileDefManager))
{
return true;
}
dungeonSpawn = tile;
return false;
});
if (dungeonSpawn == null)
{
return new List<Dungeon>()
{
Dungeon.Empty
};
}
var config = _prototype.Index(dungen.Proto);
var nextSeed = random.Next();
var dungeons = await GetDungeons(dungeonSpawn.Value, config, config.Data, config.Layers, reservedTiles, nextSeed, new Random(nextSeed));
return dungeons;
}
}

Some files were not shown because too many files have changed in this diff Show More