Add test for adding each component individually to an entity (#1870)

* Add test for adding each component individually to entities

* Put one-to-one test before all-at-once test
This commit is contained in:
DrSmugleaf
2020-08-24 13:39:00 +02:00
committed by GitHub
parent 9e6459ac79
commit a4f527351e
13 changed files with 297 additions and 114 deletions

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -61,22 +60,15 @@ namespace Content.IntegrationTests.Tests
//Iterate list of prototypes to spawn //Iterate list of prototypes to spawn
foreach (var prototype in prototypes) foreach (var prototype in prototypes)
{ {
try Assert.DoesNotThrow(() =>
{ {
Logger.LogS(LogLevel.Debug, "EntityTest", $"Testing: {prototype.ID}"); Logger.LogS(LogLevel.Debug, "EntityTest", $"Testing: {prototype.ID}");
testEntity = entityMan.SpawnEntity(prototype.ID, testLocation); testEntity = entityMan.SpawnEntity(prototype.ID, testLocation);
server.RunTicks(2); server.RunTicks(2);
Assert.That(testEntity.Initialized); Assert.That(testEntity.Initialized);
entityMan.DeleteEntity(testEntity.Uid); entityMan.DeleteEntity(testEntity.Uid);
} }, "Entity '{0}' threw an exception.",
prototype.ID);
//Fail any exceptions thrown on spawn
catch (Exception e)
{
Logger.LogS(LogLevel.Error, "EntityTest", $"Entity '{prototype.ID}' threw: {e.Message}");
Assert.Fail();
throw;
}
} }
}); });
@@ -106,6 +98,92 @@ namespace Content.IntegrationTests.Tests
await client.WaitIdleAsync(); await client.WaitIdleAsync();
} }
[Test]
public async Task AllComponentsOneToOneDeleteTest()
{
var skipComponents = new[]
{
"DebugExceptionOnAdd", // Debug components that explicitly throw exceptions
"DebugExceptionExposeData",
"DebugExceptionInitialize",
"DebugExceptionStartup",
"Map", // We aren't testing a map entity in this test
"MapGrid"
};
var testEntity = @"
- type: entity
id: AllComponentsOneToOneDeleteTestEntity";
var server = StartServerDummyTicker();
await server.WaitIdleAsync();
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var mapLoader = server.ResolveDependency<IMapLoader>();
var pauseManager = server.ResolveDependency<IPauseManager>();
var componentFactory = server.ResolveDependency<IComponentFactory>();
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
IMapGrid grid = default;
server.Post(() =>
{
// Load test entity
using var reader = new StringReader(testEntity);
prototypeManager.LoadFromStream(reader);
// Load test map
var mapId = mapManager.CreateMap();
pauseManager.AddUninitializedMap(mapId);
grid = mapLoader.LoadBlueprint(mapId, "Maps/stationstation.yml");
pauseManager.DoMapInitialize(mapId);
});
server.Assert(() =>
{
var testLocation = new GridCoordinates(new Vector2(0, 0), grid);
foreach (var type in componentFactory.AllRegisteredTypes)
{
var component = (Component) componentFactory.GetComponent(type);
// If this component is ignored
if (skipComponents.Contains(component.Name))
{
continue;
}
var entity = entityManager.SpawnEntity("AllComponentsOneToOneDeleteTestEntity", testLocation);
Assert.That(entity.Initialized);
// The component may already exist if it is a mandatory component
// such as MetaData or Transform
if (entity.HasComponent(type))
{
continue;
}
component.Owner = entity;
Logger.LogS(LogLevel.Debug, "EntityTest", $"Adding component: {component.Name}");
Assert.DoesNotThrow(() =>
{
entityManager.ComponentManager.AddComponent(entity, component);
}, "Component '{0}' threw an exception.",
component.Name);
server.RunTicks(10);
entityManager.DeleteEntity(entity.Uid);
}
});
await server.WaitIdleAsync();
}
[Test] [Test]
public async Task AllComponentsOneEntityDeleteTest() public async Task AllComponentsOneEntityDeleteTest()
{ {
@@ -184,43 +262,44 @@ namespace Content.IntegrationTests.Tests
server.Assert(() => server.Assert(() =>
{ {
Assert.DoesNotThrow(() => foreach (var distinct in distinctComponents)
{ {
foreach (var distinct in distinctComponents) var testLocation = new GridCoordinates(new Vector2(0, 0), grid);
var entity = entityManager.SpawnEntity("AllComponentsOneEntityDeleteTestEntity", testLocation);
Assert.That(entity.Initialized);
foreach (var type in distinct.components)
{ {
var testLocation = new GridCoordinates(new Vector2(0, 0), grid); var component = (Component) componentFactory.GetComponent(type);
var entity = entityManager.SpawnEntity("AllComponentsOneEntityDeleteTestEntity", testLocation);
Assert.That(entity.Initialized); // If the entity already has this component, if it was ensured or added by another
if (entity.HasComponent(component.GetType()))
foreach (var type in distinct.components)
{ {
var component = (Component) componentFactory.GetComponent(type); continue;
// If the entity already has this component, if it was ensured or added by another
if (entity.HasComponent(component.GetType()))
{
continue;
}
// If this component is ignored
if (skipComponents.Contains(component.Name))
{
continue;
}
component.Owner = entity;
Logger.LogS(LogLevel.Debug, "EntityTest", $"Adding component: {component.Name}");
entityManager.ComponentManager.AddComponent(entity, component);
} }
server.RunTicks(48); // Run one full second on the server // If this component is ignored
if (skipComponents.Contains(component.Name))
{
continue;
}
entityManager.DeleteEntity(entity.Uid); component.Owner = entity;
Logger.LogS(LogLevel.Debug, "EntityTest", $"Adding component: {component.Name}");
Assert.DoesNotThrow(() =>
{
entityManager.ComponentManager.AddComponent(entity, component);
}, "Component '{0}' threw an exception.",
component.Name);
} }
});
server.RunTicks(48); // Run one full second on the server
entityManager.DeleteEntity(entity.Uid);
}
}); });
await server.WaitIdleAsync(); await server.WaitIdleAsync();

View File

@@ -4,6 +4,7 @@ using Content.Shared.Chemistry;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -40,7 +41,14 @@ namespace Content.Server.GameObjects.Components.Chemistry
protected override void Startup() protected override void Startup()
{ {
base.Startup(); base.Startup();
Owner.GetComponent<SolutionComponent>().Capabilities |= SolutionCaps.FitsInDispenser;
if (!Owner.EnsureComponent(out SolutionComponent solution))
{
Logger.Warning(
$"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}");
}
solution.Capabilities |= SolutionCaps.FitsInDispenser;
} }
public void CancelTransformation() public void CancelTransformation()

View File

@@ -7,6 +7,7 @@ using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -19,8 +20,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
[Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IMapManager _mapManager = default!;
public override string Name => "Vapor"; public override string Name => "Vapor";
[ViewVariables]
private SolutionComponent _contents;
[ViewVariables] [ViewVariables]
private ReagentUnit _transferAmount; private ReagentUnit _transferAmount;
@@ -28,11 +27,15 @@ namespace Content.Server.GameObjects.Components.Chemistry
private Vector2 _direction; private Vector2 _direction;
private float _velocity; private float _velocity;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
_contents = Owner.GetComponent<SolutionComponent>();
if (!Owner.EnsureComponent(out SolutionComponent _))
{
Logger.Warning(
$"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}");
}
} }
public void Start(Vector2 dir, float velocity) public void Start(Vector2 dir, float velocity)
@@ -56,6 +59,9 @@ namespace Content.Server.GameObjects.Components.Chemistry
public void Update() public void Update()
{ {
if (!Owner.TryGetComponent(out SolutionComponent contents))
return;
if (!_running) if (!_running)
return; return;
@@ -70,11 +76,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
foreach (var tile in tiles) foreach (var tile in tiles)
{ {
var pos = tile.GridIndices.ToGridCoordinates(_mapManager, tile.GridIndex); var pos = tile.GridIndices.ToGridCoordinates(_mapManager, tile.GridIndex);
SpillHelper.SpillAt(pos, _contents.SplitSolution(amount), "PuddleSmear", false); //make non PuddleSmear? SpillHelper.SpillAt(pos, contents.SplitSolution(amount), "PuddleSmear", false); //make non PuddleSmear?
} }
} }
if (_contents.CurrentVolume == 0) if (contents.CurrentVolume == 0)
{ {
// Delete this // Delete this
Owner.Delete(); Owner.Delete();
@@ -87,7 +93,14 @@ namespace Content.Server.GameObjects.Components.Chemistry
{ {
return false; return false;
} }
var result = _contents.TryAddSolution(solution);
if (!Owner.TryGetComponent(out SolutionComponent contents))
{
return false;
}
var result = contents.TryAddSolution(solution);
if (!result) if (!result)
{ {
return false; return false;

View File

@@ -60,11 +60,18 @@ namespace Content.Server.GameObjects.Components.Fluids
return false; return false;
} }
var mopContents = mopComponent.Contents;
if (mopContents == null)
{
return false;
}
// Let's fill 'er up // Let's fill 'er up
// If this is called the mop should be empty but just in case we'll do Max - Current // If this is called the mop should be empty but just in case we'll do Max - Current
var transferAmount = ReagentUnit.Min(mopComponent.MaxVolume - mopComponent.CurrentVolume, CurrentVolume); var transferAmount = ReagentUnit.Min(mopComponent.MaxVolume - mopComponent.CurrentVolume, CurrentVolume);
var solution = contents.SplitSolution(transferAmount); var solution = contents.SplitSolution(transferAmount);
if (!mopComponent.Contents.TryAddSolution(solution) || mopComponent.CurrentVolume == 0) if (!mopContents.TryAddSolution(solution) || mopComponent.CurrentVolume == 0)
{ {
return false; return false;
} }
@@ -109,7 +116,14 @@ namespace Content.Server.GameObjects.Components.Fluids
return false; return false;
} }
var solution = mopComponent.Contents.SplitSolution(transferAmount); var mopContents = mopComponent.Contents;
if (mopContents == null)
{
return false;
}
var solution = mopContents.SplitSolution(transferAmount);
if (!contents.TryAddSolution(solution)) if (!contents.TryAddSolution(solution))
{ {
//This really shouldn't happen //This really shouldn't happen
@@ -127,7 +141,6 @@ namespace Content.Server.GameObjects.Components.Fluids
EntitySystem.Get<AudioSystem>().PlayFromEntity(_sound, Owner); EntitySystem.Get<AudioSystem>().PlayFromEntity(_sound, Owner);
return true; return true;
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using Content.Server.GameObjects.Components.Chemistry; #nullable enable
using Content.Server.GameObjects.Components.Chemistry;
using Content.Server.Utility; using Content.Server.Utility;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Interfaces; using Content.Shared.Interfaces;
@@ -7,6 +8,7 @@ using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Fluids namespace Content.Server.GameObjects.Components.Fluids
@@ -18,16 +20,23 @@ namespace Content.Server.GameObjects.Components.Fluids
public class MopComponent : Component, IAfterInteract public class MopComponent : Component, IAfterInteract
{ {
public override string Name => "Mop"; public override string Name => "Mop";
internal SolutionComponent Contents => _contents;
private SolutionComponent _contents; public SolutionComponent? Contents => Owner.GetComponentOrNull<SolutionComponent>();
public ReagentUnit MaxVolume public ReagentUnit MaxVolume
{ {
get => _contents.MaxVolume; get => Owner.GetComponentOrNull<SolutionComponent>()?.MaxVolume ?? ReagentUnit.Zero;
set => _contents.MaxVolume = value; set
{
if (Owner.TryGetComponent(out SolutionComponent? solution))
{
solution.MaxVolume = value;
}
}
} }
public ReagentUnit CurrentVolume => _contents.CurrentVolume; public ReagentUnit CurrentVolume =>
Owner.GetComponentOrNull<SolutionComponent>()?.CurrentVolume ?? ReagentUnit.Zero;
// Currently there's a separate amount for pickup and dropoff so // Currently there's a separate amount for pickup and dropoff so
// Picking up a puddle requires multiple clicks // Picking up a puddle requires multiple clicks
@@ -36,7 +45,7 @@ namespace Content.Server.GameObjects.Components.Fluids
public ReagentUnit PickupAmount => _pickupAmount; public ReagentUnit PickupAmount => _pickupAmount;
private ReagentUnit _pickupAmount; private ReagentUnit _pickupAmount;
private string _pickupSound; private string _pickupSound = "";
/// <inheritdoc /> /// <inheritdoc />
public override void ExposeData(ObjectSerializer serializer) public override void ExposeData(ObjectSerializer serializer)
@@ -49,12 +58,16 @@ namespace Content.Server.GameObjects.Components.Fluids
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
_contents = Owner.GetComponent<SolutionComponent>();
if (!Owner.EnsureComponent(out SolutionComponent _))
{
Logger.Warning($"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}");
}
} }
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? contents)) return;
if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return; if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return;
if (CurrentVolume <= 0) if (CurrentVolume <= 0)
@@ -66,12 +79,12 @@ namespace Content.Server.GameObjects.Components.Fluids
if (eventArgs.Target == null) if (eventArgs.Target == null)
{ {
// Drop the liquid on the mop on to the ground // Drop the liquid on the mop on to the ground
SpillHelper.SpillAt(eventArgs.ClickLocation, _contents.SplitSolution(CurrentVolume), "PuddleSmear"); SpillHelper.SpillAt(eventArgs.ClickLocation, contents.SplitSolution(CurrentVolume), "PuddleSmear");
return; return;
} }
if (!eventArgs.Target.TryGetComponent(out PuddleComponent puddleComponent)) if (!eventArgs.Target.TryGetComponent(out PuddleComponent? puddleComponent))
{ {
return; return;
} }
@@ -102,23 +115,22 @@ namespace Content.Server.GameObjects.Components.Fluids
if (puddleCleaned) //After cleaning the puddle, make a new puddle with solution from the mop as a "wet floor". Then evaporate it slowly. if (puddleCleaned) //After cleaning the puddle, make a new puddle with solution from the mop as a "wet floor". Then evaporate it slowly.
{ {
SpillHelper.SpillAt(eventArgs.ClickLocation, _contents.SplitSolution(transferAmount), "PuddleSmear"); SpillHelper.SpillAt(eventArgs.ClickLocation, contents.SplitSolution(transferAmount), "PuddleSmear");
} }
else else
{ {
_contents.SplitSolution(transferAmount); contents.SplitSolution(transferAmount);
} }
// Give some visual feedback shit's happening (for anyone who can't hear sound) // Give some visual feedback shit's happening (for anyone who can't hear sound)
Owner.PopupMessage(eventArgs.User, Loc.GetString("Swish")); Owner.PopupMessage(eventArgs.User, Loc.GetString("Swish"));
if (_pickupSound == null) if (string.IsNullOrWhiteSpace(_pickupSound))
{ {
return; return;
} }
EntitySystem.Get<AudioSystem>().PlayFromEntity(_pickupSound, Owner); EntitySystem.Get<AudioSystem>().PlayFromEntity(_pickupSound, Owner);
} }
} }
} }

View File

@@ -115,6 +115,7 @@ namespace Content.Server.GameObjects.Components.Fluids
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
if (Owner.TryGetComponent(out SolutionComponent solutionComponent)) if (Owner.TryGetComponent(out SolutionComponent solutionComponent))
{ {
_contents = solutionComponent; _contents = solutionComponent;
@@ -122,7 +123,6 @@ namespace Content.Server.GameObjects.Components.Fluids
else else
{ {
_contents = Owner.AddComponent<SolutionComponent>(); _contents = Owner.AddComponent<SolutionComponent>();
_contents.Initialize();
} }
_snapGrid = Owner.EnsureComponent<SnapGridComponent>(); _snapGrid = Owner.EnsureComponent<SnapGridComponent>();

View File

@@ -8,6 +8,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -45,13 +46,17 @@ namespace Content.Server.GameObjects.Components.Fluids
set => _sprayVelocity = value; set => _sprayVelocity = value;
} }
private SolutionComponent _contents; public ReagentUnit CurrentVolume => Owner.GetComponentOrNull<SolutionComponent>()?.CurrentVolume ?? ReagentUnit.Zero;
public ReagentUnit CurrentVolume => _contents.CurrentVolume;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
_contents = Owner.GetComponent<SolutionComponent>();
if (!Owner.EnsureComponent(out SolutionComponent _))
{
Logger.Warning(
$"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}");
}
} }
public override void ExposeData(ObjectSerializer serializer) public override void ExposeData(ObjectSerializer serializer)
@@ -74,8 +79,11 @@ namespace Content.Server.GameObjects.Components.Fluids
if (eventArgs.ClickLocation.GridID != playerPos.GridID) if (eventArgs.ClickLocation.GridID != playerPos.GridID)
return; return;
if (!Owner.TryGetComponent(out SolutionComponent contents))
return;
var direction = (eventArgs.ClickLocation.Position - playerPos.Position).Normalized; var direction = (eventArgs.ClickLocation.Position - playerPos.Position).Normalized;
var solution = _contents.SplitSolution(_transferAmount); var solution = contents.SplitSolution(_transferAmount);
playerPos = playerPos.Offset(direction); // Move a bit so we don't hit the player playerPos = playerPos.Offset(direction); // Move a bit so we don't hit the player
//TODO: check for wall? //TODO: check for wall?

View File

@@ -17,6 +17,7 @@ using Content.Server.GameObjects.Components.Body;
using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Server.GameObjects.EntitySystems.DoAfter;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using System; using System;
using Robust.Shared.Log;
namespace Content.Server.GameObjects.Components.Movement namespace Content.Server.GameObjects.Components.Movement
{ {
@@ -39,14 +40,17 @@ namespace Content.Server.GameObjects.Components.Movement
[ViewVariables] [ViewVariables]
private float _climbDelay; private float _climbDelay;
private ICollidableComponent _collidableComponent;
private DoAfterSystem _doAfterSystem; private DoAfterSystem _doAfterSystem;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
_collidableComponent = Owner.GetComponent<ICollidableComponent>(); if (!Owner.EnsureComponent(out CollidableComponent _))
{
Logger.Warning($"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(CollidableComponent)}");
}
_doAfterSystem = EntitySystem.Get<DoAfterSystem>(); _doAfterSystem = EntitySystem.Get<DoAfterSystem>();
} }

View File

@@ -3,8 +3,8 @@ using System.Collections.Generic;
using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -22,14 +22,6 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
[ViewVariables] [ViewVariables]
private EmergencyLightState _lightState = EmergencyLightState.Charging; private EmergencyLightState _lightState = EmergencyLightState.Charging;
[ViewVariables]
private BatteryComponent Battery => Owner.GetComponent<BatteryComponent>();
[ViewVariables]
private PointLightComponent Light => Owner.GetComponent<PointLightComponent>();
[ViewVariables]
private PowerReceiverComponent PowerReceiver => Owner.GetComponent<PowerReceiverComponent>();
private SpriteComponent Sprite => Owner.GetComponent<SpriteComponent>();
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
private float _wattage; private float _wattage;
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
@@ -58,9 +50,14 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
/// </summary> /// </summary>
public void UpdateState() public void UpdateState()
{ {
if (PowerReceiver.Powered) if (!Owner.TryGetComponent(out PowerReceiverComponent receiver))
{ {
PowerReceiver.Load = (int) Math.Abs(_wattage); return;
}
if (receiver.Powered)
{
receiver.Load = (int) Math.Abs(_wattage);
TurnOff(); TurnOff();
_lightState = EmergencyLightState.Charging; _lightState = EmergencyLightState.Charging;
} }
@@ -76,9 +73,14 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
if (_lightState == EmergencyLightState.Empty if (_lightState == EmergencyLightState.Empty
|| _lightState == EmergencyLightState.Full) return; || _lightState == EmergencyLightState.Full) return;
if (!Owner.TryGetComponent(out BatteryComponent battery))
{
return;
}
if(_lightState == EmergencyLightState.On) if(_lightState == EmergencyLightState.On)
{ {
if (!Battery.TryUseCharge(_wattage * frameTime)) if (!battery.TryUseCharge(_wattage * frameTime))
{ {
_lightState = EmergencyLightState.Empty; _lightState = EmergencyLightState.Empty;
TurnOff(); TurnOff();
@@ -86,10 +88,14 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
} }
else else
{ {
Battery.CurrentCharge += _chargingWattage * frameTime * _chargingEfficiency; battery.CurrentCharge += _chargingWattage * frameTime * _chargingEfficiency;
if (Battery.BatteryState == BatteryState.Full) if (battery.BatteryState == BatteryState.Full)
{ {
PowerReceiver.Load = 1; if (Owner.TryGetComponent(out PowerReceiverComponent receiver))
{
receiver.Load = 1;
}
_lightState = EmergencyLightState.Full; _lightState = EmergencyLightState.Full;
} }
} }
@@ -97,25 +103,49 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
private void TurnOff() private void TurnOff()
{ {
Sprite.LayerSetState(0, "emergency_light_off"); if (Owner.TryGetComponent(out SpriteComponent sprite))
Light.Enabled = false; {
sprite.LayerSetState(0, "emergency_light_off");
}
if (Owner.TryGetComponent(out PointLightComponent light))
{
light.Enabled = false;
}
} }
private void TurnOn() private void TurnOn()
{ {
Sprite.LayerSetState(0, "emergency_light_on"); if (Owner.TryGetComponent(out SpriteComponent sprite))
Light.Enabled = true; {
sprite.LayerSetState(0, "emergency_light_on");
}
if (Owner.TryGetComponent(out PointLightComponent light))
{
light.Enabled = true;
}
} }
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
Owner.GetComponent<PowerReceiverComponent>().OnPowerStateChanged += UpdateState;
if (!Owner.EnsureComponent(out PowerReceiverComponent receiver))
{
Logger.Warning($"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(PowerReceiverComponent)}");
}
receiver.OnPowerStateChanged += UpdateState;
} }
public override void OnRemove() public override void OnRemove()
{ {
Owner.GetComponent<PowerReceiverComponent>().OnPowerStateChanged -= UpdateState; if (Owner.TryGetComponent(out PowerReceiverComponent receiver))
{
receiver.OnPowerStateChanged -= UpdateState;
}
base.OnRemove(); base.OnRemove();
} }
@@ -132,7 +162,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
On On
} }
public Dictionary<EmergencyLightState, string> BatteryStateText = new Dictionary<EmergencyLightState, String> public Dictionary<EmergencyLightState, string> BatteryStateText = new Dictionary<EmergencyLightState, string>
{ {
{ EmergencyLightState.Full, "[color=darkgreen]Full[/color]"}, { EmergencyLightState.Full, "[color=darkgreen]Full[/color]"},
{ EmergencyLightState.Empty, "[color=darkred]Empty[/color]"}, { EmergencyLightState.Empty, "[color=darkred]Empty[/color]"},

View File

@@ -4,6 +4,7 @@ using Content.Shared.GameObjects.EntitySystems;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Timing; using Robust.Shared.Interfaces.Timing;
using Robust.Shared.Log;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -19,8 +20,6 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
{ {
public override string Name => "SolarPanel"; public override string Name => "SolarPanel";
private PowerSupplierComponent _powerSupplier;
/// <summary> /// <summary>
/// Maximum supply output by this panel (coverage = 1) /// Maximum supply output by this panel (coverage = 1)
/// </summary> /// </summary>
@@ -64,15 +63,21 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
private void UpdateSupply() private void UpdateSupply()
{ {
if (_powerSupplier != null) if (Owner.TryGetComponent(out PowerSupplierComponent supplier))
_powerSupplier.SupplyRate = (int) (_maxSupply * _coverage); {
supplier.SupplyRate = (int) (_maxSupply * _coverage);
}
} }
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
_powerSupplier = Owner.GetComponent<PowerSupplierComponent>(); if (!Owner.EnsureComponent(out PowerSupplierComponent _))
{
Logger.Warning($"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(PowerSupplierComponent)}");
}
UpdateSupply(); UpdateSupply();
} }

View File

@@ -1,4 +1,3 @@
using System;
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Components;
@@ -32,10 +31,11 @@ namespace Content.Server.GameObjects.Components.Projectiles
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
if (!Owner.HasComponent<ProjectileComponent>())
if (!Owner.EnsureComponent(out ProjectileComponent _))
{ {
Logger.Error("StunProjectile entity must have a ProjectileComponent"); Logger.Warning(
throw new InvalidOperationException(); $"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(ProjectileComponent)}");
} }
} }

View File

@@ -28,6 +28,7 @@ using Robust.Shared.Random;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Damage;
using Robust.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
{ {
@@ -157,7 +158,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
public override void OnAdd() public override void OnAdd()
{ {
base.OnAdd(); base.OnAdd();
var rangedWeaponComponent = Owner.GetComponent<ServerRangedWeaponComponent>();
if (!Owner.EnsureComponent(out ServerRangedWeaponComponent rangedWeaponComponent))
{
Logger.Warning(
$"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(ServerRangedWeaponComponent)}");
}
rangedWeaponComponent.Barrel ??= this; rangedWeaponComponent.Barrel ??= this;
rangedWeaponComponent.FireHandler += Fire; rangedWeaponComponent.FireHandler += Fire;

View File

@@ -37,7 +37,6 @@ namespace Content.Server.GameObjects.Components
[Dependency] private readonly IServerNotifyManager _notifyManager = default!; [Dependency] private readonly IServerNotifyManager _notifyManager = default!;
private AudioSystem _audioSystem = default!; private AudioSystem _audioSystem = default!;
private AppearanceComponent _appearance = default!;
private bool _isPanelOpen; private bool _isPanelOpen;
@@ -105,7 +104,10 @@ namespace Content.Server.GameObjects.Components
private void UpdateAppearance() private void UpdateAppearance()
{ {
_appearance.SetData(WiresVisuals.MaintenancePanelState, IsPanelOpen && IsPanelVisible); if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(WiresVisuals.MaintenancePanelState, IsPanelOpen && IsPanelVisible);
}
} }
/// <summary> /// <summary>
@@ -148,8 +150,11 @@ namespace Content.Server.GameObjects.Components
{ {
base.Initialize(); base.Initialize();
_audioSystem = EntitySystem.Get<AudioSystem>(); _audioSystem = EntitySystem.Get<AudioSystem>();
_appearance = Owner.GetComponent<AppearanceComponent>();
_appearance.SetData(WiresVisuals.MaintenancePanelState, IsPanelOpen); if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(WiresVisuals.MaintenancePanelState, IsPanelOpen);
}
if (UserInterface != null) if (UserInterface != null)
{ {