Add a test that puts all components on an entity and checks for no exceptions (#1815)
* Add test that puts all components on an entity and checks for no exceptions Also fix all the exceptions that happened because of this * Add comments to the test * Fix nullable errors * Fix more nullable errors * More nullable error fixes * Unignore basic actor component * Fix more nullable errors * NULLABLE ERROR * Add string interpolation * Merge if checks * Remove redundant pragma warning disable 649 * Address reviews * Remove null wrappers around TryGetComponent * Merge conflict fixes * APC battery component error fix * Fix power test * Fix atmos mapgrid usages
This commit is contained in:
@@ -17,9 +17,7 @@ namespace Content.Client.GameObjects.Components.Body
|
||||
[ComponentReference(typeof(IBodyManagerComponent))]
|
||||
public class BodyManagerComponent : SharedBodyManagerComponent, IClientDraggable
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public bool ClientCanDropOn(CanDropEventArgs eventArgs)
|
||||
{
|
||||
|
||||
@@ -27,13 +27,9 @@ namespace Content.Client.GameObjects.Components.Instruments
|
||||
/// </summary>
|
||||
public event Action? OnMidiPlaybackEnded;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IMidiManager _midiManager = default!;
|
||||
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
private IMidiRenderer? _renderer;
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@ namespace Content.Client.GameObjects.Components.Items
|
||||
{
|
||||
private HandsGui? _gui;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
/// <inheritdoc />
|
||||
private readonly List<Hand> _hands = new List<Hand>();
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.Doors;
|
||||
using Content.Shared.Physics;
|
||||
using NUnit.Framework;
|
||||
using Robust.Server.Console.Commands;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Prototypes;
|
||||
using static Content.Server.GameObjects.Components.Doors.ServerDoorComponent;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Doors
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Robust.Server.Interfaces.Maps;
|
||||
@@ -11,6 +14,7 @@ using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Logger = Robust.Shared.Log.Logger;
|
||||
|
||||
namespace Content.IntegrationTests.Tests
|
||||
{
|
||||
@@ -30,7 +34,7 @@ namespace Content.IntegrationTests.Tests
|
||||
var pauseMan = server.ResolveDependency<IPauseManager>();
|
||||
var prototypes = new List<EntityPrototype>();
|
||||
IMapGrid grid = default;
|
||||
IEntity testEntity = null;
|
||||
IEntity testEntity;
|
||||
|
||||
//Build up test environment
|
||||
server.Post(() =>
|
||||
@@ -59,7 +63,7 @@ namespace Content.IntegrationTests.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogS(LogLevel.Debug, "EntityTest", "Testing: " + prototype.ID);
|
||||
Logger.LogS(LogLevel.Debug, "EntityTest", $"Testing: {prototype.ID}");
|
||||
testEntity = entityMan.SpawnEntity(prototype.ID, testLocation);
|
||||
server.RunTicks(2);
|
||||
Assert.That(testEntity.Initialized);
|
||||
@@ -69,8 +73,8 @@ namespace Content.IntegrationTests.Tests
|
||||
//Fail any exceptions thrown on spawn
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogS(LogLevel.Error, "EntityTest", "Entity '" + prototype.ID + "' threw: " + e.Message);
|
||||
//Assert.Fail();
|
||||
Logger.LogS(LogLevel.Error, "EntityTest", $"Entity '{prototype.ID}' threw: {e.Message}");
|
||||
Assert.Fail();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -101,5 +105,125 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
await client.WaitIdleAsync();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task AllComponentsOneEntityDeleteTest()
|
||||
{
|
||||
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: AllComponentsOneEntityDeleteTestEntity";
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
var distinctComponents = new List<(List<Type> components, List<Type> references)>
|
||||
{
|
||||
(new List<Type>(), new List<Type>())
|
||||
};
|
||||
|
||||
// Split components into groups, ensuring that their references don't conflict
|
||||
foreach (var type in componentFactory.AllRegisteredTypes)
|
||||
{
|
||||
var registration = componentFactory.GetRegistration(type);
|
||||
|
||||
for (var i = 0; i < distinctComponents.Count; i++)
|
||||
{
|
||||
var distinct = distinctComponents[i];
|
||||
|
||||
if (distinct.references.Intersect(registration.References).Any())
|
||||
{
|
||||
// Ensure the next list if this one has conflicting references
|
||||
if (i + 1 >= distinctComponents.Count)
|
||||
{
|
||||
distinctComponents.Add((new List<Type>(), new List<Type>()));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the component and its references if no conflicting references were found
|
||||
distinct.components.Add(type);
|
||||
distinct.references.AddRange(registration.References);
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
Assert.That(distinctComponents, Is.Not.Empty);
|
||||
|
||||
server.Assert(() =>
|
||||
{
|
||||
Assert.DoesNotThrow(() =>
|
||||
{
|
||||
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 component = (Component) componentFactory.GetComponent(type);
|
||||
|
||||
// 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
|
||||
|
||||
entityManager.DeleteEntity(entity.Uid);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ namespace Content.IntegrationTests.Tests
|
||||
Assert.That(apcEnt.TryGetComponent<ApcComponent>(out var apc));
|
||||
Assert.That(apcExtensionEnt.TryGetComponent<PowerProviderComponent>(out var provider));
|
||||
Assert.That(powerReceiverEnt.TryGetComponent(out receiver));
|
||||
Assert.NotNull(apc.Battery);
|
||||
|
||||
provider.PowerTransferRange = 5; //arbitrary range to reach receiver
|
||||
receiver.PowerReceptionRange = 5; //arbitrary range to reach provider
|
||||
|
||||
@@ -20,10 +20,8 @@ namespace Content.Server.Atmos
|
||||
[RegisterComponent]
|
||||
public class GasSprayerComponent : Component, IAfterInteract
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
//TODO: create a function that can create a gas based on a solution mix
|
||||
public override string Name => "GasSprayer";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
using Content.Server.Interfaces;
|
||||
@@ -15,6 +16,7 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Access
|
||||
{
|
||||
@@ -22,16 +24,19 @@ namespace Content.Server.GameObjects.Components.Access
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class IdCardConsoleComponent : SharedIdCardConsoleComponent, IActivate
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
private ContainerSlot _privilegedIdContainer;
|
||||
private ContainerSlot _targetIdContainer;
|
||||
private AccessReader _accessReader;
|
||||
private ContainerSlot _privilegedIdContainer = default!;
|
||||
private ContainerSlot _targetIdContainer = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(IdCardConsoleUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -40,16 +45,30 @@ namespace Content.Server.GameObjects.Components.Access
|
||||
_privilegedIdContainer = ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-privilegedId", Owner);
|
||||
_targetIdContainer = ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-targetId", Owner);
|
||||
|
||||
_accessReader = Owner.GetComponent<AccessReader>();
|
||||
if (!Owner.EnsureComponent(out AccessReader _))
|
||||
{
|
||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} didn't have a {nameof(AccessReader)}");
|
||||
}
|
||||
|
||||
if (UserInterface == null)
|
||||
{
|
||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} doesn't have a {nameof(ServerUserInterfaceComponent)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(IdCardConsoleUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
UpdateUserInterface();
|
||||
}
|
||||
|
||||
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
if (obj.Session.AttachedEntity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (obj.Message)
|
||||
{
|
||||
case IdButtonPressedMessage msg:
|
||||
@@ -72,13 +91,19 @@ namespace Content.Server.GameObjects.Components.Access
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if there is an ID in <see cref="_privilegedIdContainer"/> and said ID satisfies the requirements of <see cref="_accessReader"/>.
|
||||
/// Returns true if there is an ID in <see cref="_privilegedIdContainer"/> and said ID satisfies the requirements of <see cref="AccessReader"/>.
|
||||
/// </summary>
|
||||
private bool PrivilegedIdIsAuthorized()
|
||||
{
|
||||
var privilegedIdEntity = _privilegedIdContainer.ContainedEntity;
|
||||
return privilegedIdEntity != null && _accessReader.IsAllowed(privilegedIdEntity);
|
||||
if (!Owner.TryGetComponent(out AccessReader? reader))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var privilegedIdEntity = _privilegedIdContainer.ContainedEntity;
|
||||
return privilegedIdEntity != null && reader.IsAllowed(privilegedIdEntity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the "Submit" button in the UI gets pressed.
|
||||
/// Writes data passed from the UI into the ID stored in <see cref="_targetIdContainer"/>, if present.
|
||||
@@ -110,7 +135,7 @@ namespace Content.Server.GameObjects.Components.Access
|
||||
/// </summary>
|
||||
private void HandleId(IEntity user, ContainerSlot container)
|
||||
{
|
||||
if (!user.TryGetComponent(out IHandsComponent hands))
|
||||
if (!user.TryGetComponent(out IHandsComponent? hands))
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user, _localizationManager.GetString("You have no hands."));
|
||||
return;
|
||||
@@ -133,7 +158,13 @@ namespace Content.Server.GameObjects.Components.Access
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(!hands.Drop(hands.ActiveHand, container))
|
||||
|
||||
if (hands.ActiveHand == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hands.Drop(hands.ActiveHand, container))
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user, _localizationManager.GetString("You can't let go of the ID card!"));
|
||||
return;
|
||||
@@ -185,17 +216,17 @@ namespace Content.Server.GameObjects.Components.Access
|
||||
_privilegedIdContainer.ContainedEntity?.Name ?? "",
|
||||
_targetIdContainer.ContainedEntity?.Name ?? "");
|
||||
}
|
||||
_userInterface.SetState(newState);
|
||||
UserInterface?.SetState(newState);
|
||||
}
|
||||
|
||||
public void Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if(!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if(!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.Transform;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -13,7 +14,6 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
[RegisterComponent]
|
||||
public class AirtightComponent : Component, IMapInit
|
||||
{
|
||||
private SnapGridComponent _snapGrid;
|
||||
private (GridId, MapIndices) _lastPosition;
|
||||
|
||||
public override string Name => "Airtight";
|
||||
@@ -28,7 +28,11 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
set
|
||||
{
|
||||
_airBlocked = value;
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID)?.Invalidate(_snapGrid.Position);
|
||||
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID)?.Invalidate(snapGrid.Position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,19 +52,23 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
base.Initialize();
|
||||
|
||||
// Using the SnapGrid is critical for the performance of the room builder, and thus if
|
||||
// it is absent the component will not be airtight. An exception is much easier to track
|
||||
// down than the object magically not being airtight, so throw one if the SnapGrid component
|
||||
// it is absent the component will not be airtight. A warning is much easier to track
|
||||
// down than the object magically not being airtight, so log one if the SnapGrid component
|
||||
// is missing.
|
||||
if (!Owner.TryGetComponent(out _snapGrid))
|
||||
throw new Exception("Airtight entities must have a SnapGrid component");
|
||||
if (!Owner.EnsureComponent(out SnapGridComponent _))
|
||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition.ToString()} doesn't have a {nameof(SnapGridComponent)}");
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
public void MapInit()
|
||||
{
|
||||
_snapGrid.OnPositionChanged += OnTransformMove;
|
||||
_lastPosition = (Owner.Transform.GridID, _snapGrid.Position);
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
snapGrid.OnPositionChanged += OnTransformMove;
|
||||
_lastPosition = (Owner.Transform.GridID, snapGrid.Position);
|
||||
}
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
@@ -70,11 +78,15 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
_airBlocked = false;
|
||||
|
||||
_snapGrid.OnPositionChanged -= OnTransformMove;
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
snapGrid.OnPositionChanged -= OnTransformMove;
|
||||
|
||||
if(_fixVacuum)
|
||||
if (_fixVacuum)
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID)?
|
||||
.FixVacuum(_snapGrid.Position);
|
||||
.FixVacuum(snapGrid.Position);
|
||||
}
|
||||
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
@@ -83,15 +95,24 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
UpdatePosition(_lastPosition.Item1, _lastPosition.Item2);
|
||||
UpdatePosition();
|
||||
_lastPosition = (Owner.Transform.GridID, _snapGrid.Position);
|
||||
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
_lastPosition = (Owner.Transform.GridID, snapGrid.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePosition() => UpdatePosition(Owner.Transform.GridID, _snapGrid.Position);
|
||||
private void UpdatePosition()
|
||||
{
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
UpdatePosition(Owner.Transform.GridID, snapGrid.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePosition(GridId gridId, MapIndices pos)
|
||||
{
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(gridId)?.Invalidate(pos);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,30 +16,37 @@ using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class GasAnalyzerComponent : SharedGasAnalyzerComponent, IAfterInteract, IDropped, IUse
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private IMapManager _mapManager = default!;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
|
||||
private BoundUserInterface _userInterface = default!;
|
||||
private GasAnalyzerDanger _pressureDanger;
|
||||
private float _timeSinceSync;
|
||||
private const float TimeBetweenSyncs = 2f;
|
||||
private bool _checkPlayer = false; // Check at the player pos or at some other tile?
|
||||
private GridCoordinates? _position; // The tile that we scanned
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(GasAnalyzerUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(GasAnalyzerUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
@@ -56,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
_checkPlayer = true;
|
||||
_position = null;
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
UpdateUserInterface();
|
||||
Resync();
|
||||
}
|
||||
@@ -71,7 +78,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
_checkPlayer = false;
|
||||
_position = pos;
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
UpdateUserInterface();
|
||||
Resync();
|
||||
}
|
||||
@@ -79,7 +86,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
public void CloseInterface(IPlayerSession session)
|
||||
{
|
||||
_position = null;
|
||||
_userInterface.Close(session);
|
||||
UserInterface?.Close(session);
|
||||
Resync();
|
||||
}
|
||||
|
||||
@@ -123,10 +130,15 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
private void UpdateUserInterface()
|
||||
{
|
||||
if (UserInterface == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string? error = null;
|
||||
|
||||
// Check if the player is still holding the gas analyzer => if not, don't update
|
||||
foreach (var session in _userInterface.SubscribedSessions)
|
||||
foreach (var session in UserInterface.SubscribedSessions)
|
||||
{
|
||||
if (session.AttachedEntity == null)
|
||||
return;
|
||||
@@ -156,7 +168,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
if (tile == null)
|
||||
{
|
||||
error = "No Atmosphere!";
|
||||
_userInterface.SetState(
|
||||
UserInterface.SetState(
|
||||
new GasAnalyzerBoundUserInterfaceState(
|
||||
0,
|
||||
0,
|
||||
@@ -166,7 +178,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
}
|
||||
|
||||
var gases = new List<GasEntry>();
|
||||
for (int i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
{
|
||||
var gas = Atmospherics.GetGas(i);
|
||||
|
||||
@@ -175,7 +187,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
gases.Add(new GasEntry(gas.Name, tile.Gases[i], gas.Color));
|
||||
}
|
||||
|
||||
_userInterface.SetState(
|
||||
UserInterface.SetState(
|
||||
new GasAnalyzerBoundUserInterfaceState(
|
||||
tile.Pressure,
|
||||
tile.Temperature,
|
||||
|
||||
@@ -6,16 +6,21 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class GasMixtureComponent : Component
|
||||
public class GasMixtureHolderComponent : Component
|
||||
{
|
||||
public override string Name => "GasMixture";
|
||||
public override string Name => "GasMixtureHolder";
|
||||
|
||||
[ViewVariables] public GasMixture GasMixture { get; set; } = new GasMixture();
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(this, x => GasMixture.Volume, "volume", 0f);
|
||||
|
||||
serializer.DataReadWriteFunction(
|
||||
"volume",
|
||||
0f,
|
||||
vol => GasMixture.Volume = vol,
|
||||
() => GasMixture.Volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -50,7 +51,6 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
private float _timer = 0f;
|
||||
private Stopwatch _stopwatch = new Stopwatch();
|
||||
public int UpdateCounter { get; private set; } = 0;
|
||||
private IMapGrid _grid;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly HashSet<ExcitedGroup> _excitedGroups = new HashSet<ExcitedGroup>(1000);
|
||||
@@ -89,42 +89,40 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
/// <inheritdoc />
|
||||
public void PryTile(MapIndices indices)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGridComponent)) return;
|
||||
if (IsSpace(indices) || IsAirBlocked(indices)) return;
|
||||
|
||||
var tile = _grid.GetTileRef(indices).Tile;
|
||||
var mapGrid = mapGridComponent.Grid;
|
||||
var tile = mapGrid.GetTileRef(indices).Tile;
|
||||
|
||||
var tileDefinitionManager = IoCManager.Resolve<ITileDefinitionManager>();
|
||||
var tileDef = (ContentTileDefinition)tileDefinitionManager[tile.TypeId];
|
||||
|
||||
var underplating = tileDefinitionManager["underplating"];
|
||||
_grid.SetTile(indices, new Tile(underplating.TileId));
|
||||
mapGrid.SetTile(indices, new Tile(underplating.TileId));
|
||||
|
||||
//Actually spawn the relevant tile item at the right position and give it some offset to the corner.
|
||||
var tileItem = IoCManager.Resolve<IServerEntityManager>().SpawnEntity(tileDef.ItemDropPrototypeName, new GridCoordinates(indices.X, indices.Y, _grid));
|
||||
var tileItem = IoCManager.Resolve<IServerEntityManager>().SpawnEntity(tileDef.ItemDropPrototypeName, new GridCoordinates(indices.X, indices.Y, mapGrid));
|
||||
tileItem.Transform.WorldPosition += (0.2f, 0.2f);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_grid = Owner.GetComponent<IMapGridComponent>().Grid;
|
||||
|
||||
RepopulateTiles();
|
||||
}
|
||||
|
||||
public override void OnAdd()
|
||||
{
|
||||
base.OnAdd();
|
||||
|
||||
_grid = Owner.GetComponent<IMapGridComponent>().Grid;
|
||||
|
||||
RepopulateTiles();
|
||||
}
|
||||
|
||||
public void RepopulateTiles()
|
||||
{
|
||||
foreach (var tile in _grid.GetAllTiles())
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
|
||||
foreach (var tile in mapGrid.Grid.GetAllTiles())
|
||||
{
|
||||
if(!_tiles.ContainsKey(tile.GridIndices))
|
||||
_tiles.Add(tile.GridIndices, new TileAtmosphere(this, tile.GridIndex, tile.GridIndices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}));
|
||||
@@ -145,6 +143,8 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
private void Revalidate()
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
|
||||
foreach (var indices in _invalidatedCoords.ToArray())
|
||||
{
|
||||
var tile = GetTile(indices);
|
||||
@@ -152,7 +152,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
if (tile == null)
|
||||
{
|
||||
tile = new TileAtmosphere(this, _grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C});
|
||||
tile = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C});
|
||||
_tiles[indices] = tile;
|
||||
}
|
||||
|
||||
@@ -199,8 +199,9 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
/// <inheritdoc />
|
||||
public void FixVacuum(MapIndices indices)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
var tile = GetTile(indices);
|
||||
if (tile?.GridIndex != _grid.Index) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index) return;
|
||||
var adjacent = GetAdjacentTiles(indices);
|
||||
tile.Air = new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C};
|
||||
_tiles[indices] = tile;
|
||||
@@ -217,16 +218,17 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddActiveTile(TileAtmosphere tile)
|
||||
public void AddActiveTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile?.GridIndex != _grid.Index || tile?.Air == null) return;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index || tile?.Air == null) return;
|
||||
tile.Excited = true;
|
||||
_activeTiles.Add(tile);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void RemoveActiveTile(TileAtmosphere tile)
|
||||
public void RemoveActiveTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile == null) return;
|
||||
_activeTiles.Remove(tile);
|
||||
@@ -236,27 +238,29 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddHotspotTile(TileAtmosphere tile)
|
||||
public void AddHotspotTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile?.GridIndex != _grid.Index || tile?.Air == null) return;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index || tile?.Air == null) return;
|
||||
_hotspotTiles.Add(tile);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void RemoveHotspotTile(TileAtmosphere tile)
|
||||
public void RemoveHotspotTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile == null) return;
|
||||
_hotspotTiles.Remove(tile);
|
||||
}
|
||||
|
||||
public void AddSuperconductivityTile(TileAtmosphere tile)
|
||||
public void AddSuperconductivityTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile?.GridIndex != _grid.Index) return;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index) return;
|
||||
_superconductivityTiles.Add(tile);
|
||||
}
|
||||
|
||||
public void RemoveSuperconductivityTile(TileAtmosphere tile)
|
||||
public void RemoveSuperconductivityTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile == null) return;
|
||||
_superconductivityTiles.Remove(tile);
|
||||
@@ -264,9 +268,10 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddHighPressureDelta(TileAtmosphere tile)
|
||||
public void AddHighPressureDelta(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile?.GridIndex != _grid.Index) return;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index) return;
|
||||
_highPressureDelta.Add(tile);
|
||||
}
|
||||
|
||||
@@ -292,20 +297,22 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public TileAtmosphere GetTile(GridCoordinates coordinates)
|
||||
public TileAtmosphere? GetTile(GridCoordinates coordinates)
|
||||
{
|
||||
return GetTile(coordinates.ToMapIndices(_mapManager));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public TileAtmosphere GetTile(MapIndices indices)
|
||||
public TileAtmosphere? GetTile(MapIndices indices)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return null;
|
||||
|
||||
if (_tiles.TryGetValue(indices, out var tile)) return tile;
|
||||
|
||||
// We don't have that tile!
|
||||
if (IsSpace(indices))
|
||||
{
|
||||
var space = new TileAtmosphere(this, _grid.Index, indices, new GasMixture(int.MaxValue){Temperature = Atmospherics.TCMB});
|
||||
var space = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(int.MaxValue){Temperature = Atmospherics.TCMB});
|
||||
space.Air.MarkImmutable();
|
||||
return space;
|
||||
}
|
||||
@@ -324,7 +331,9 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
public bool IsSpace(MapIndices indices)
|
||||
{
|
||||
// TODO ATMOS use ContentTileDefinition to define in YAML whether or not a tile is considered space
|
||||
return _grid.GetTileRef(indices).Tile.IsEmpty;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||
|
||||
return mapGrid.Grid.GetTileRef(indices).Tile.IsEmpty;
|
||||
}
|
||||
|
||||
public Dictionary<Direction, TileAtmosphere> GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false)
|
||||
@@ -334,7 +343,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
var side = indices.Offset(dir);
|
||||
var tile = GetTile(side);
|
||||
if(tile?.Air != null || includeAirBlocked)
|
||||
if (tile != null && (tile.Air != null || includeAirBlocked))
|
||||
sides[dir] = tile;
|
||||
}
|
||||
|
||||
@@ -349,7 +358,9 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
/// <inheritdoc />
|
||||
public float GetVolumeForCells(int cellCount)
|
||||
{
|
||||
return _grid.TileSize * cellCount * Atmospherics.CellVolume;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||
|
||||
return mapGrid.Grid.TileSize * cellCount * Atmospherics.CellVolume;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -509,9 +520,11 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
}
|
||||
}
|
||||
|
||||
private AirtightComponent GetObstructingComponent(MapIndices indices)
|
||||
private AirtightComponent? GetObstructingComponent(MapIndices indices)
|
||||
{
|
||||
foreach (var v in _grid.GetSnapGridCell(indices, SnapGridOffset.Center))
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||
|
||||
foreach (var v in mapGrid.Grid.GetSnapGridCell(indices, SnapGridOffset.Center))
|
||||
{
|
||||
if (v.Owner.TryGetComponent<AirtightComponent>(out var ac))
|
||||
return ac;
|
||||
@@ -534,22 +547,24 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
if (serializer.Reading)
|
||||
if (serializer.Reading &&
|
||||
Owner.TryGetComponent(out IMapGridComponent? mapGrid))
|
||||
{
|
||||
var gridId = Owner.GetComponent<IMapGridComponent>().Grid.Index;
|
||||
var gridId = mapGrid.Grid.Index;
|
||||
|
||||
if (!serializer.TryReadDataField("uniqueMixes", out List<GasMixture> uniqueMixes) ||
|
||||
!serializer.TryReadDataField("tiles", out Dictionary<MapIndices, int> tiles))
|
||||
if (!serializer.TryReadDataField("uniqueMixes", out List<GasMixture>? uniqueMixes) ||
|
||||
!serializer.TryReadDataField("tiles", out Dictionary<MapIndices, int>? tiles))
|
||||
return;
|
||||
|
||||
_tiles.Clear();
|
||||
|
||||
foreach (var (indices, mix) in tiles)
|
||||
foreach (var (indices, mix) in tiles!)
|
||||
{
|
||||
_tiles.Add(indices, new TileAtmosphere(this, gridId, indices, (GasMixture)uniqueMixes[mix].Clone()));
|
||||
_tiles.Add(indices, new TileAtmosphere(this, gridId, indices, (GasMixture)uniqueMixes![mix].Clone()));
|
||||
Invalidate(indices);
|
||||
}
|
||||
} else if (serializer.Writing)
|
||||
}
|
||||
else if (serializer.Writing)
|
||||
{
|
||||
var uniqueMixes = new List<GasMixture>();
|
||||
var uniqueMixHash = new Dictionary<GasMixture, int>();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
#nullable enable
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
@@ -19,18 +20,13 @@ namespace Content.Server.GameObjects.Components.BarSign
|
||||
{
|
||||
public override string Name => "BarSign";
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
|
||||
private string _currentSign;
|
||||
|
||||
private PowerReceiverComponent _power;
|
||||
private SpriteComponent _sprite;
|
||||
private string? _currentSign;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string CurrentSign
|
||||
public string? CurrentSign
|
||||
{
|
||||
get => _currentSign;
|
||||
set
|
||||
@@ -40,6 +36,8 @@ namespace Content.Server.GameObjects.Components.BarSign
|
||||
}
|
||||
}
|
||||
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
private void UpdateSignInfo()
|
||||
{
|
||||
if (_currentSign == null)
|
||||
@@ -53,15 +51,18 @@ namespace Content.Server.GameObjects.Components.BarSign
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_power.Powered)
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||
{
|
||||
_sprite.LayerSetState(0, "empty");
|
||||
_sprite.LayerSetShader(0, "shaded");
|
||||
if (!Powered)
|
||||
{
|
||||
sprite.LayerSetState(0, "empty");
|
||||
sprite.LayerSetShader(0, "shaded");
|
||||
}
|
||||
else
|
||||
{
|
||||
_sprite.LayerSetState(0, prototype.Icon);
|
||||
_sprite.LayerSetShader(0, "unshaded");
|
||||
sprite.LayerSetState(0, prototype.Icon);
|
||||
sprite.LayerSetShader(0, "unshaded");
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(prototype.Name))
|
||||
@@ -80,21 +81,25 @@ namespace Content.Server.GameObjects.Components.BarSign
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_power = Owner.GetComponent<PowerReceiverComponent>();
|
||||
_sprite = Owner.GetComponent<SpriteComponent>();
|
||||
|
||||
_power.OnPowerStateChanged += PowerOnOnPowerStateChanged;
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged += PowerOnOnPowerStateChanged;
|
||||
}
|
||||
|
||||
UpdateSignInfo();
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
_power.OnPowerStateChanged -= PowerOnOnPowerStateChanged;
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged -= PowerOnOnPowerStateChanged;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
private void PowerOnOnPowerStateChanged(object sender, PowerStateEventArgs e)
|
||||
private void PowerOnOnPowerStateChanged(object? sender, PowerStateEventArgs e)
|
||||
{
|
||||
UpdateSignInfo();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Body;
|
||||
using Content.Shared.Body.Scanner;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Server.GameObjects.Components.UserInterface;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Body
|
||||
{
|
||||
@@ -12,32 +15,44 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class BodyScannerComponent : Component, IActivate
|
||||
{
|
||||
private BoundUserInterface _userInterface;
|
||||
public sealed override string Name => "BodyScanner";
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(BodyScannerUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor) ||
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor) ||
|
||||
actor.playerSession.AttachedEntity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (actor.playerSession.AttachedEntity.TryGetComponent(out BodyManagerComponent attempt))
|
||||
if (actor.playerSession.AttachedEntity.TryGetComponent(out BodyManagerComponent? attempt))
|
||||
{
|
||||
var state = InterfaceState(attempt.Template, attempt.Parts);
|
||||
_userInterface.SetState(state);
|
||||
UserInterface?.SetState(state);
|
||||
}
|
||||
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(BodyScannerUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
|
||||
if (UserInterface == null)
|
||||
{
|
||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} doesn't have a {nameof(ServerUserInterfaceComponent)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage serverMsg) { }
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Body.Circulatory;
|
||||
using Content.Server.GameObjects.Components.Chemistry;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.GameObjects.Components.Nutrition;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -20,24 +19,20 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
|
||||
[RegisterComponent]
|
||||
public class StomachComponent : SharedStomachComponent
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
/// <summary>
|
||||
/// Max volume of internal solution storage
|
||||
/// </summary>
|
||||
public ReagentUnit MaxVolume
|
||||
{
|
||||
get => _stomachContents.MaxVolume;
|
||||
set => _stomachContents.MaxVolume = value;
|
||||
get => Owner.TryGetComponent(out SolutionComponent? solution) ? solution.MaxVolume : ReagentUnit.Zero;
|
||||
set
|
||||
{
|
||||
if (Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
solution.MaxVolume = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal solution storage
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
private SolutionComponent _stomachContents;
|
||||
|
||||
/// <summary>
|
||||
/// Initial internal solution storage volume
|
||||
@@ -68,20 +63,29 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
_stomachContents = Owner.GetComponent<SolutionComponent>();
|
||||
_stomachContents.MaxVolume = _initialMaxVolume;
|
||||
if (!Owner.EnsureComponent(out SolutionComponent solution))
|
||||
{
|
||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}");
|
||||
}
|
||||
|
||||
solution.MaxVolume = _initialMaxVolume;
|
||||
}
|
||||
|
||||
public bool TryTransferSolution(Solution solution)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solutionComponent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: For now no partial transfers. Potentially change by design
|
||||
if (solution.TotalVolume + _stomachContents.CurrentVolume > _stomachContents.MaxVolume)
|
||||
if (solution.TotalVolume + solutionComponent.CurrentVolume > solutionComponent.MaxVolume)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add solution to _stomachContents
|
||||
_stomachContents.TryAddSolution(solution, false, true);
|
||||
solutionComponent.TryAddSolution(solution, false, true);
|
||||
// Add each reagent to _reagentDeltas. Used to track how long each reagent has been in the stomach
|
||||
foreach (var reagent in solution.Contents)
|
||||
{
|
||||
@@ -99,7 +103,8 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
|
||||
/// <param name="frameTime">The time since the last update in seconds.</param>
|
||||
public void Update(float frameTime)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out BloodstreamComponent bloodstream))
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solutionComponent) ||
|
||||
!Owner.TryGetComponent(out BloodstreamComponent? bloodstream))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -114,7 +119,7 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
|
||||
delta.Increment(frameTime);
|
||||
if (delta.Lifetime > _digestionDelay)
|
||||
{
|
||||
_stomachContents.TryRemoveReagent(delta.ReagentId, delta.Quantity);
|
||||
solutionComponent.TryRemoveReagent(delta.ReagentId, delta.Quantity);
|
||||
transferSolution.AddReagent(delta.ReagentId, delta.Quantity);
|
||||
_reagentDeltas.Remove(delta);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Shared.Interfaces;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -6,6 +7,7 @@ using Content.Server.Body;
|
||||
using Content.Shared.Body.Surgery;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameObjects.Components.UserInterface;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
@@ -21,20 +23,23 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
[RegisterComponent]
|
||||
public class DroppedBodyPartComponent : Component, IAfterInteract, IBodyPartContainer
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager = default!;
|
||||
|
||||
private readonly Dictionary<int, object> _optionsCache = new Dictionary<int, object>();
|
||||
private BodyManagerComponent _bodyManagerComponentCache;
|
||||
private BodyManagerComponent? _bodyManagerComponentCache;
|
||||
private int _idHash;
|
||||
private IEntity _performerCache;
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
private IEntity? _performerCache;
|
||||
|
||||
public sealed override string Name => "DroppedBodyPart";
|
||||
|
||||
[ViewVariables] public BodyPart ContainedBodyPart { get; private set; }
|
||||
[ViewVariables] public BodyPart ContainedBodyPart { get; private set; } = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(GenericSurgeryUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||
{
|
||||
@@ -48,7 +53,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
_performerCache = null;
|
||||
_bodyManagerComponentCache = null;
|
||||
|
||||
if (eventArgs.Target.TryGetComponent(out BodyManagerComponent bodyManager))
|
||||
if (eventArgs.Target.TryGetComponent(out BodyManagerComponent? bodyManager))
|
||||
{
|
||||
SendBodySlotListToUser(eventArgs, bodyManager);
|
||||
}
|
||||
@@ -58,9 +63,10 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(GenericSurgeryUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public void TransferBodyPartData(BodyPart data)
|
||||
@@ -68,7 +74,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
ContainedBodyPart = data;
|
||||
Owner.Name = Loc.GetString(ContainedBodyPart.Name);
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent component))
|
||||
if (Owner.TryGetComponent(out SpriteComponent? component))
|
||||
{
|
||||
component.LayerSetRSI(0, data.RSIPath);
|
||||
component.LayerSetState(0, data.RSIState);
|
||||
@@ -91,7 +97,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
foreach (var slot in unoccupiedSlots)
|
||||
{
|
||||
if (!bodyManager.TryGetSlotType(slot, out var typeResult) ||
|
||||
typeResult != ContainedBodyPart.PartType ||
|
||||
typeResult != ContainedBodyPart?.PartType ||
|
||||
!bodyManager.TryGetBodyPartConnections(slot, out var parts))
|
||||
{
|
||||
continue;
|
||||
@@ -129,7 +135,18 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
/// </summary>
|
||||
private void HandleReceiveBodyPartSlot(int key)
|
||||
{
|
||||
CloseSurgeryUI(_performerCache.GetComponent<BasicActorComponent>().playerSession);
|
||||
if (_performerCache == null ||
|
||||
!_performerCache.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CloseSurgeryUI(actor.playerSession);
|
||||
|
||||
if (_bodyManagerComponentCache == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
|
||||
if (!_optionsCache.TryGetValue(key, out var targetObject))
|
||||
@@ -138,34 +155,42 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
Loc.GetString("You see no useful way to attach {0:theName} anymore.", Owner));
|
||||
}
|
||||
|
||||
var target = targetObject as string;
|
||||
var target = (string) targetObject!;
|
||||
string message;
|
||||
|
||||
if (_bodyManagerComponentCache.InstallDroppedBodyPart(this, target))
|
||||
{
|
||||
message = Loc.GetString("You attach {0:theName}.", ContainedBodyPart);
|
||||
}
|
||||
else
|
||||
{
|
||||
message = Loc.GetString("You can't attach it!");
|
||||
}
|
||||
|
||||
_sharedNotifyManager.PopupMessage(
|
||||
_bodyManagerComponentCache.Owner,
|
||||
_performerCache,
|
||||
!_bodyManagerComponentCache.InstallDroppedBodyPart(this, target)
|
||||
? Loc.GetString("You can't attach it!")
|
||||
: Loc.GetString("You attach {0:theName}.", ContainedBodyPart));
|
||||
message);
|
||||
}
|
||||
|
||||
private void OpenSurgeryUI(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
private void UpdateSurgeryUIBodyPartSlotRequest(IPlayerSession session, Dictionary<string, int> options)
|
||||
{
|
||||
_userInterface.SendMessage(new RequestBodyPartSlotSurgeryUIMessage(options), session);
|
||||
UserInterface?.SendMessage(new RequestBodyPartSlotSurgeryUIMessage(options), session);
|
||||
}
|
||||
|
||||
private void CloseSurgeryUI(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Close(session);
|
||||
UserInterface?.Close(session);
|
||||
}
|
||||
|
||||
private void CloseAllSurgeryUIs()
|
||||
{
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Body;
|
||||
using Content.Server.Body.Mechanisms;
|
||||
@@ -8,14 +8,15 @@ using Content.Shared.Interfaces;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameObjects.Components.UserInterface;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Body
|
||||
@@ -26,24 +27,27 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
[RegisterComponent]
|
||||
public class DroppedMechanismComponent : Component, IAfterInteract
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager;
|
||||
[Dependency] private IPrototypeManager _prototypeManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public sealed override string Name => "DroppedMechanism";
|
||||
|
||||
private readonly Dictionary<int, object> _optionsCache = new Dictionary<int, object>();
|
||||
|
||||
private BodyManagerComponent _bodyManagerComponentCache;
|
||||
private BodyManagerComponent? _bodyManagerComponentCache;
|
||||
|
||||
private int _idHash;
|
||||
|
||||
private IEntity _performerCache;
|
||||
private IEntity? _performerCache;
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
[ViewVariables] public Mechanism ContainedMechanism { get; private set; } = default!;
|
||||
|
||||
[ViewVariables] public Mechanism ContainedMechanism { get; private set; }
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(GenericSurgeryUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||
{
|
||||
@@ -63,12 +67,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
}
|
||||
else if (eventArgs.Target.TryGetComponent<DroppedBodyPartComponent>(out var droppedBodyPart))
|
||||
{
|
||||
if (droppedBodyPart.ContainedBodyPart == null)
|
||||
{
|
||||
Logger.Debug(
|
||||
"Installing a mechanism was attempted on an IEntity with a DroppedBodyPartComponent that doesn't have a BodyPart in it!");
|
||||
throw new InvalidOperationException("A DroppedBodyPartComponent exists without a BodyPart in it!");
|
||||
}
|
||||
DebugTools.AssertNotNull(droppedBodyPart.ContainedBodyPart);
|
||||
|
||||
if (!droppedBodyPart.ContainedBodyPart.TryInstallDroppedMechanism(this))
|
||||
{
|
||||
@@ -82,9 +81,10 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(GenericSurgeryUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeDroppedMechanism(Mechanism data)
|
||||
@@ -92,7 +92,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
ContainedMechanism = data;
|
||||
Owner.Name = Loc.GetString(ContainedMechanism.Name);
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent component))
|
||||
if (Owner.TryGetComponent(out SpriteComponent? component))
|
||||
{
|
||||
component.LayerSetRSI(0, data.RSIPath);
|
||||
component.LayerSetState(0, data.RSIState);
|
||||
@@ -111,7 +111,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
|
||||
if (serializer.Reading && debugLoadMechanismData != "")
|
||||
{
|
||||
_prototypeManager.TryIndex(debugLoadMechanismData, out MechanismPrototype data);
|
||||
_prototypeManager.TryIndex(debugLoadMechanismData!, out MechanismPrototype data);
|
||||
|
||||
var mechanism = new Mechanism(data);
|
||||
mechanism.EnsureInitialize();
|
||||
@@ -155,7 +155,18 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
/// </summary>
|
||||
private void HandleReceiveBodyPart(int key)
|
||||
{
|
||||
CloseSurgeryUI(_performerCache.GetComponent<BasicActorComponent>().playerSession);
|
||||
if (_performerCache == null ||
|
||||
!_performerCache.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CloseSurgeryUI(actor.playerSession);
|
||||
|
||||
if (_bodyManagerComponentCache == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
|
||||
if (!_optionsCache.TryGetValue(key, out var targetObject))
|
||||
@@ -165,36 +176,37 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
return;
|
||||
}
|
||||
|
||||
var target = targetObject as BodyPart;
|
||||
var target = (BodyPart) targetObject;
|
||||
var message = target.TryInstallDroppedMechanism(this)
|
||||
? Loc.GetString("You jam the {0} inside {1:them}.", ContainedMechanism.Name, _performerCache)
|
||||
: Loc.GetString("You can't fit it in!");
|
||||
|
||||
_sharedNotifyManager.PopupMessage(
|
||||
_bodyManagerComponentCache.Owner,
|
||||
_performerCache,
|
||||
!target.TryInstallDroppedMechanism(this)
|
||||
? Loc.GetString("You can't fit it in!")
|
||||
: Loc.GetString("You jam the {1} inside {0:them}.", _performerCache, ContainedMechanism.Name));
|
||||
message);
|
||||
|
||||
// TODO: {1:theName}
|
||||
}
|
||||
|
||||
private void OpenSurgeryUI(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
private void UpdateSurgeryUIBodyPartRequest(IPlayerSession session, Dictionary<string, int> options)
|
||||
{
|
||||
_userInterface.SendMessage(new RequestBodyPartSurgeryUIMessage(options), session);
|
||||
UserInterface?.SendMessage(new RequestBodyPartSurgeryUIMessage(options), session);
|
||||
}
|
||||
|
||||
private void CloseSurgeryUI(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Close(session);
|
||||
UserInterface?.Close(session);
|
||||
}
|
||||
|
||||
private void CloseAllSurgeryUIs()
|
||||
{
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Body;
|
||||
using Content.Server.Body.Mechanisms;
|
||||
@@ -18,6 +19,8 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Body
|
||||
{
|
||||
@@ -30,9 +33,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
[RegisterComponent]
|
||||
public class SurgeryToolComponent : Component, ISurgeon, IAfterInteract
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager = default!;
|
||||
|
||||
public override string Name => "SurgeryTool";
|
||||
public override uint? NetID => ContentNetIDs.SURGERY;
|
||||
@@ -41,17 +42,22 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
|
||||
private float _baseOperateTime;
|
||||
|
||||
private BodyManagerComponent _bodyManagerComponentCache;
|
||||
private BodyManagerComponent? _bodyManagerComponentCache;
|
||||
|
||||
private ISurgeon.MechanismRequestCallback _callbackCache;
|
||||
private ISurgeon.MechanismRequestCallback? _callbackCache;
|
||||
|
||||
private int _idHash;
|
||||
|
||||
private IEntity _performerCache;
|
||||
private IEntity? _performerCache;
|
||||
|
||||
private SurgeryType _surgeryType;
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(GenericSurgeryUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||
{
|
||||
@@ -60,7 +66,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
return;
|
||||
}
|
||||
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -73,7 +79,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
_callbackCache = null;
|
||||
|
||||
// Attempt surgery on a BodyManagerComponent by sending a list of operable BodyParts to the client to choose from
|
||||
if (eventArgs.Target.TryGetComponent(out BodyManagerComponent body))
|
||||
if (eventArgs.Target.TryGetComponent(out BodyManagerComponent? body))
|
||||
{
|
||||
// Create dictionary to send to client (text to be shown : data sent back if selected)
|
||||
var toSend = new Dictionary<string, int>();
|
||||
@@ -105,13 +111,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
// Attempt surgery on a DroppedBodyPart - there's only one possible target so no need for selection UI
|
||||
_performerCache = eventArgs.User;
|
||||
|
||||
if (droppedBodyPart.ContainedBodyPart == null)
|
||||
{
|
||||
// Throw error if the DroppedBodyPart has no data in it.
|
||||
Logger.Debug(
|
||||
"Surgery was attempted on an IEntity with a DroppedBodyPartComponent that doesn't have a BodyPart in it!");
|
||||
throw new InvalidOperationException("A DroppedBodyPartComponent exists without a BodyPart in it!");
|
||||
}
|
||||
DebugTools.AssertNotNull(droppedBodyPart.ContainedBodyPart);
|
||||
|
||||
// If surgery can be performed...
|
||||
if (!droppedBodyPart.ContainedBodyPart.SurgeryCheck(_surgeryType))
|
||||
@@ -144,7 +144,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
toSend.Add(mechanism.Name, _idHash++);
|
||||
}
|
||||
|
||||
if (_optionsCache.Count > 0)
|
||||
if (_optionsCache.Count > 0 && _performerCache != null)
|
||||
{
|
||||
OpenSurgeryUI(_performerCache.GetComponent<BasicActorComponent>().playerSession);
|
||||
UpdateSurgeryUIMechanismRequest(_performerCache.GetComponent<BasicActorComponent>().playerSession,
|
||||
@@ -162,34 +162,35 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(GenericSurgeryUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenSurgeryUI(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
private void UpdateSurgeryUIBodyPartRequest(IPlayerSession session, Dictionary<string, int> options)
|
||||
{
|
||||
_userInterface.SendMessage(new RequestBodyPartSurgeryUIMessage(options), session);
|
||||
UserInterface?.SendMessage(new RequestBodyPartSurgeryUIMessage(options), session);
|
||||
}
|
||||
|
||||
private void UpdateSurgeryUIMechanismRequest(IPlayerSession session, Dictionary<string, int> options)
|
||||
{
|
||||
_userInterface.SendMessage(new RequestMechanismSurgeryUIMessage(options), session);
|
||||
UserInterface?.SendMessage(new RequestMechanismSurgeryUIMessage(options), session);
|
||||
}
|
||||
|
||||
private void CloseSurgeryUI(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Close(session);
|
||||
UserInterface?.Close(session);
|
||||
}
|
||||
|
||||
private void CloseAllSurgeryUIs()
|
||||
{
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message)
|
||||
@@ -211,14 +212,22 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
/// </summary>
|
||||
private void HandleReceiveBodyPart(int key)
|
||||
{
|
||||
CloseSurgeryUI(_performerCache.GetComponent<BasicActorComponent>().playerSession);
|
||||
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
|
||||
if (!_optionsCache.TryGetValue(key, out var targetObject))
|
||||
if (_performerCache == null ||
|
||||
!_performerCache.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
SendNoUsefulWayToUseAnymorePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
var target = targetObject as BodyPart;
|
||||
CloseSurgeryUI(actor.playerSession);
|
||||
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
|
||||
if (!_optionsCache.TryGetValue(key, out var targetObject) ||
|
||||
_bodyManagerComponentCache == null)
|
||||
{
|
||||
SendNoUsefulWayToUseAnymorePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
var target = (BodyPart) targetObject!;
|
||||
|
||||
if (!target.AttemptSurgery(_surgeryType, _bodyManagerComponentCache, this, _performerCache))
|
||||
{
|
||||
@@ -233,19 +242,27 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
private void HandleReceiveMechanism(int key)
|
||||
{
|
||||
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
|
||||
if (!_optionsCache.TryGetValue(key, out var targetObject))
|
||||
if (!_optionsCache.TryGetValue(key, out var targetObject) ||
|
||||
_performerCache == null ||
|
||||
!_performerCache.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
SendNoUsefulWayToUseAnymorePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
var target = targetObject as Mechanism;
|
||||
|
||||
CloseSurgeryUI(_performerCache.GetComponent<BasicActorComponent>().playerSession);
|
||||
_callbackCache(target, _bodyManagerComponentCache, this, _performerCache);
|
||||
CloseSurgeryUI(actor.playerSession);
|
||||
_callbackCache?.Invoke(target, _bodyManagerComponentCache, this, _performerCache);
|
||||
}
|
||||
|
||||
private void SendNoUsefulWayToUsePopup()
|
||||
{
|
||||
if (_bodyManagerComponentCache == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_sharedNotifyManager.PopupMessage(
|
||||
_bodyManagerComponentCache.Owner,
|
||||
_performerCache,
|
||||
@@ -254,6 +271,11 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
|
||||
private void SendNoUsefulWayToUseAnymorePopup()
|
||||
{
|
||||
if (_bodyManagerComponentCache == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_sharedNotifyManager.PopupMessage(
|
||||
_bodyManagerComponentCache.Owner,
|
||||
_performerCache,
|
||||
|
||||
@@ -34,13 +34,11 @@ namespace Content.Server.GameObjects.Components.Buckle
|
||||
[RegisterComponent]
|
||||
public class BuckleComponent : SharedBuckleComponent, IInteractHand, IDragDrop
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
private int _size;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -19,21 +20,11 @@ namespace Content.Server.GameObjects.Components.Cargo
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class CargoConsoleComponent : SharedCargoConsoleComponent, IActivate
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ICargoOrderDataManager _cargoOrderDataManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
[ViewVariables]
|
||||
public int Points = 1000;
|
||||
|
||||
private BoundUserInterface _userInterface = default!;
|
||||
|
||||
[ViewVariables]
|
||||
public GalacticMarketComponent Market { get; private set; } = default!;
|
||||
|
||||
[ViewVariables]
|
||||
public CargoOrderDatabaseComponent Orders { get; private set; } = default!;
|
||||
|
||||
private CargoBankAccount? _bankAccount;
|
||||
|
||||
[ViewVariables]
|
||||
@@ -65,22 +56,49 @@ namespace Content.Server.GameObjects.Components.Cargo
|
||||
|
||||
private bool _requestOnly = false;
|
||||
|
||||
private PowerReceiverComponent _powerReceiver = default!;
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
private CargoConsoleSystem _cargoConsoleSystem = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(CargoConsoleUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
Market = Owner.GetComponent<GalacticMarketComponent>();
|
||||
Orders = Owner.GetComponent<CargoOrderDatabaseComponent>();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(CargoConsoleUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
|
||||
if (!Owner.EnsureComponent(out GalacticMarketComponent _))
|
||||
{
|
||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} had no {nameof(GalacticMarketComponent)}");
|
||||
}
|
||||
|
||||
if (!Owner.EnsureComponent(out CargoOrderDatabaseComponent _))
|
||||
{
|
||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} had no {nameof(GalacticMarketComponent)}");
|
||||
}
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
|
||||
_cargoConsoleSystem = EntitySystem.Get<CargoConsoleSystem>();
|
||||
BankAccount = _cargoConsoleSystem.StationAccount;
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from YAML
|
||||
/// </summary>
|
||||
@@ -93,8 +111,13 @@ namespace Content.Server.GameObjects.Components.Cargo
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage serverMsg)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out CargoOrderDatabaseComponent? orders))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var message = serverMsg.Message;
|
||||
if (!Orders.ConnectedToDatabase)
|
||||
if (!orders.ConnectedToDatabase)
|
||||
return;
|
||||
if (!Powered)
|
||||
return;
|
||||
@@ -107,39 +130,39 @@ namespace Content.Server.GameObjects.Components.Cargo
|
||||
break;
|
||||
}
|
||||
|
||||
_cargoOrderDataManager.AddOrder(Orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id);
|
||||
_cargoOrderDataManager.AddOrder(orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id);
|
||||
break;
|
||||
}
|
||||
case CargoConsoleRemoveOrderMessage msg:
|
||||
{
|
||||
_cargoOrderDataManager.RemoveOrder(Orders.Database.Id, msg.OrderNumber);
|
||||
_cargoOrderDataManager.RemoveOrder(orders.Database.Id, msg.OrderNumber);
|
||||
break;
|
||||
}
|
||||
case CargoConsoleApproveOrderMessage msg:
|
||||
{
|
||||
if (_requestOnly ||
|
||||
!Orders.Database.TryGetOrder(msg.OrderNumber, out var order) ||
|
||||
!orders.Database.TryGetOrder(msg.OrderNumber, out var order) ||
|
||||
_bankAccount == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_prototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product);
|
||||
if (product == null)
|
||||
if (product == null!)
|
||||
break;
|
||||
var capacity = _cargoOrderDataManager.GetCapacity(Orders.Database.Id);
|
||||
var capacity = _cargoOrderDataManager.GetCapacity(orders.Database.Id);
|
||||
if (capacity.CurrentCapacity == capacity.MaxCapacity)
|
||||
break;
|
||||
if (!_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount))
|
||||
break;
|
||||
_cargoOrderDataManager.ApproveOrder(Orders.Database.Id, msg.OrderNumber);
|
||||
_cargoOrderDataManager.ApproveOrder(orders.Database.Id, msg.OrderNumber);
|
||||
UpdateUIState();
|
||||
break;
|
||||
}
|
||||
case CargoConsoleShuttleMessage _:
|
||||
{
|
||||
var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(Orders.Database);
|
||||
Orders.Database.ClearOrderCapacity();
|
||||
var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database);
|
||||
orders.Database.ClearOrderCapacity();
|
||||
// TODO replace with shuttle code
|
||||
|
||||
// TEMPORARY loop for spawning stuff on top of console
|
||||
@@ -166,12 +189,12 @@ namespace Content.Server.GameObjects.Components.Cargo
|
||||
if (!Powered)
|
||||
return;
|
||||
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
|
||||
private void UpdateUIState()
|
||||
{
|
||||
if (_bankAccount == null)
|
||||
if (_bankAccount == null || !Owner.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -180,7 +203,7 @@ namespace Content.Server.GameObjects.Components.Cargo
|
||||
var name = _bankAccount.Name;
|
||||
var balance = _bankAccount.Balance;
|
||||
var capacity = _cargoOrderDataManager.GetCapacity(id);
|
||||
_userInterface.SetState(new CargoConsoleInterfaceState(_requestOnly, id, name, balance, capacity));
|
||||
UserInterface?.SetState(new CargoConsoleInterfaceState(_requestOnly, id, name, balance, capacity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
@@ -40,24 +42,26 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
[ComponentReference(typeof(IInteractUsing))]
|
||||
public class ChemMasterComponent : SharedChemMasterComponent, IActivate, IInteractUsing, ISolutionChange
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
|
||||
|
||||
[ViewVariables] private BoundUserInterface _userInterface;
|
||||
[ViewVariables] private ContainerSlot _beakerContainer;
|
||||
[ViewVariables] private string _packPrototypeId;
|
||||
[ViewVariables] private ContainerSlot _beakerContainer = default!;
|
||||
[ViewVariables] private string _packPrototypeId = "";
|
||||
|
||||
[ViewVariables] private bool HasBeaker => _beakerContainer.ContainedEntity != null;
|
||||
|
||||
[ViewVariables] private bool BufferModeTransfer = true;
|
||||
[ViewVariables] private bool _bufferModeTransfer = true;
|
||||
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
private readonly SolutionComponent BufferSolution = new SolutionComponent();
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(ChemMasterUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
/// <summary>
|
||||
/// Shows the serializer how to save/load this components yaml prototype.
|
||||
@@ -77,14 +81,19 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(ChemMasterUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
_beakerContainer =
|
||||
ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-reagentContainerContainer", Owner);
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
_powerReceiver.OnPowerStateChanged += OnPowerChanged;
|
||||
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged += OnPowerChanged;
|
||||
}
|
||||
|
||||
//BufferSolution = Owner.BufferSolution
|
||||
BufferSolution.Solution = new Solution();
|
||||
@@ -93,7 +102,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
UpdateUserInterface();
|
||||
}
|
||||
|
||||
private void OnPowerChanged(object sender, PowerStateEventArgs e)
|
||||
private void OnPowerChanged(object? sender, PowerStateEventArgs e)
|
||||
{
|
||||
UpdateUserInterface();
|
||||
}
|
||||
@@ -105,6 +114,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// <param name="obj">A user interface message from the client.</param>
|
||||
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
if (obj.Session.AttachedEntity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = (UiActionMessage) obj.Message;
|
||||
var needsPower = msg.action switch
|
||||
{
|
||||
@@ -124,11 +138,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
TransferReagent(msg.id, msg.amount, msg.isBuffer);
|
||||
break;
|
||||
case UiAction.Transfer:
|
||||
BufferModeTransfer = true;
|
||||
_bufferModeTransfer = true;
|
||||
UpdateUserInterface();
|
||||
break;
|
||||
case UiAction.Discard:
|
||||
BufferModeTransfer = false;
|
||||
_bufferModeTransfer = false;
|
||||
UpdateUserInterface();
|
||||
break;
|
||||
case UiAction.CreatePills:
|
||||
@@ -147,7 +161,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// </summary>
|
||||
/// <param name="playerEntity">The player entity.</param>
|
||||
/// <returns>Returns true if the entity can use the chem master, and false if it cannot.</returns>
|
||||
private bool PlayerCanUseChemMaster(IEntity playerEntity, bool needsPower = true)
|
||||
private bool PlayerCanUseChemMaster(IEntity? playerEntity, bool needsPower = true)
|
||||
{
|
||||
//Need player entity to check if they are still able to use the chem master
|
||||
if (playerEntity == null)
|
||||
@@ -172,18 +186,18 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
if (beaker == null)
|
||||
{
|
||||
return new ChemMasterBoundUserInterfaceState(Powered, false, ReagentUnit.New(0), ReagentUnit.New(0),
|
||||
"", Owner.Name, null, BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
|
||||
"", Owner.Name, new List<Solution.ReagentQuantity>(), BufferSolution.ReagentList.ToList(), _bufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
|
||||
}
|
||||
|
||||
var solution = beaker.GetComponent<SolutionComponent>();
|
||||
return new ChemMasterBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume,
|
||||
beaker.Name, Owner.Name, solution.ReagentList.ToList(), BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
|
||||
beaker.Name, Owner.Name, solution.ReagentList.ToList(), BufferSolution.ReagentList.ToList(), _bufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
|
||||
}
|
||||
|
||||
private void UpdateUserInterface()
|
||||
{
|
||||
var state = GetUserInterfaceState();
|
||||
_userInterface.SetState(state);
|
||||
UserInterface?.SetState(state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -207,7 +221,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
|
||||
private void TransferReagent(string id, ReagentUnit amount, bool isBuffer)
|
||||
{
|
||||
if (!HasBeaker && BufferModeTransfer) return;
|
||||
if (!HasBeaker && _bufferModeTransfer) return;
|
||||
var beaker = _beakerContainer.ContainedEntity;
|
||||
var beakerSolution = beaker.GetComponent<SolutionComponent>();
|
||||
if (isBuffer)
|
||||
@@ -227,7 +241,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
}
|
||||
|
||||
BufferSolution.Solution.RemoveReagent(id, actualAmount);
|
||||
if (BufferModeTransfer)
|
||||
if (_bufferModeTransfer)
|
||||
{
|
||||
beakerSolution.Solution.AddReagent(id, actualAmount);
|
||||
}
|
||||
@@ -351,12 +365,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// <param name="args">Data relevant to the event such as the actor which triggered it.</param>
|
||||
void IActivate.Activate(ActivateEventArgs args)
|
||||
{
|
||||
if (!args.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!args.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.User.TryGetComponent(out IHandsComponent hands))
|
||||
if (!args.User.TryGetComponent(out IHandsComponent? hands))
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
|
||||
_localizationManager.GetString("You have no hands."));
|
||||
@@ -366,7 +380,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
var activeHandEntity = hands.GetActiveHand?.Owner;
|
||||
if (activeHandEntity == null)
|
||||
{
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,13 +393,20 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// <returns></returns>
|
||||
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs args)
|
||||
{
|
||||
if (!args.User.TryGetComponent(out IHandsComponent hands))
|
||||
if (!args.User.TryGetComponent(out IHandsComponent? hands))
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
|
||||
_localizationManager.GetString("You have no hands."));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hands.GetActiveHand == null)
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
|
||||
Loc.GetString("You have nothing on your hand."));
|
||||
return false;
|
||||
}
|
||||
|
||||
var activeHandEntity = hands.GetActiveHand.Owner;
|
||||
if (activeHandEntity.TryGetComponent<SolutionComponent>(out var solution))
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using Content.Server.GameObjects.Components.Body.Circulatory;
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Server.Utility;
|
||||
@@ -22,9 +23,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
[RegisterComponent]
|
||||
public class InjectorComponent : SharedInjectorComponent, IAfterInteract, IUse
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the injector is able to draw from containers or if it's a single use
|
||||
@@ -53,11 +52,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
private InjectorToggleMode _toggleState;
|
||||
/// <summary>
|
||||
/// Internal solution container
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
private SolutionComponent _internalContents;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
@@ -69,9 +63,15 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
_internalContents = Owner.GetComponent<SolutionComponent>();
|
||||
_internalContents.Capabilities |= SolutionCaps.Injector;
|
||||
//Set _toggleState based on prototype
|
||||
|
||||
Owner.EnsureComponent<SolutionComponent>();
|
||||
|
||||
if (Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
solution.Capabilities |= SolutionCaps.Injector;
|
||||
}
|
||||
|
||||
// Set _toggleState based on prototype
|
||||
_toggleState = _injectOnly ? InjectorToggleMode.Inject : InjectorToggleMode.Draw;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return;
|
||||
|
||||
//Make sure we have the attacking entity
|
||||
if (eventArgs.Target == null || !_internalContents.Injector)
|
||||
if (eventArgs.Target == null || !Owner.TryGetComponent(out SolutionComponent? solution) || !solution.Injector)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
}
|
||||
else //Handle injecting into bloodstream
|
||||
{
|
||||
if (targetEntity.TryGetComponent(out BloodstreamComponent bloodstream) &&
|
||||
if (targetEntity.TryGetComponent(out BloodstreamComponent? bloodstream) &&
|
||||
_toggleState == InjectorToggleMode.Inject)
|
||||
{
|
||||
TryInjectIntoBloodstream(bloodstream, eventArgs.User);
|
||||
@@ -155,7 +155,8 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
|
||||
private void TryInjectIntoBloodstream(BloodstreamComponent targetBloodstream, IEntity user)
|
||||
{
|
||||
if (_internalContents.CurrentVolume == 0)
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solution) ||
|
||||
solution.CurrentVolume == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -170,7 +171,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
}
|
||||
|
||||
//Move units from attackSolution to targetSolution
|
||||
var removedSolution = _internalContents.SplitSolution(realTransferAmount);
|
||||
var removedSolution = solution.SplitSolution(realTransferAmount);
|
||||
if (!targetBloodstream.TryTransferSolution(removedSolution))
|
||||
{
|
||||
return;
|
||||
@@ -183,7 +184,8 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
|
||||
private void TryInject(SolutionComponent targetSolution, IEntity user)
|
||||
{
|
||||
if (_internalContents.CurrentVolume == 0)
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solution) ||
|
||||
solution.CurrentVolume == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -198,7 +200,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
}
|
||||
|
||||
//Move units from attackSolution to targetSolution
|
||||
var removedSolution = _internalContents.SplitSolution(realTransferAmount);
|
||||
var removedSolution = solution.SplitSolution(realTransferAmount);
|
||||
if (!targetSolution.TryAddSolution(removedSolution))
|
||||
{
|
||||
return;
|
||||
@@ -211,7 +213,8 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
|
||||
private void TryDraw(SolutionComponent targetSolution, IEntity user)
|
||||
{
|
||||
if (_internalContents.EmptyVolume == 0)
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solution) ||
|
||||
solution.EmptyVolume == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -227,7 +230,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
|
||||
//Move units from attackSolution to targetSolution
|
||||
var removedSolution = targetSolution.SplitSolution(realTransferAmount);
|
||||
if (!_internalContents.TryAddSolution(removedSolution))
|
||||
if (!solution.TryAddSolution(removedSolution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -239,7 +242,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new InjectorComponentState(_internalContents.CurrentVolume, _internalContents.MaxVolume, _toggleState);
|
||||
Owner.TryGetComponent(out SolutionComponent? solution);
|
||||
|
||||
var currentVolume = solution?.CurrentVolume ?? ReagentUnit.Zero;
|
||||
var maxVolume = solution?.MaxVolume ?? ReagentUnit.Zero;
|
||||
|
||||
return new InjectorComponentState(currentVolume, maxVolume, _toggleState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
@@ -38,14 +39,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
[ComponentReference(typeof(IInteractUsing))]
|
||||
public class ReagentDispenserComponent : SharedReagentDispenserComponent, IActivate, IInteractUsing, ISolutionChange
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
|
||||
|
||||
[ViewVariables] private BoundUserInterface _userInterface;
|
||||
[ViewVariables] private ContainerSlot _beakerContainer;
|
||||
[ViewVariables] private string _packPrototypeId;
|
||||
[ViewVariables] private ContainerSlot _beakerContainer = default!;
|
||||
[ViewVariables] private string _packPrototypeId = "";
|
||||
|
||||
[ViewVariables] private bool HasBeaker => _beakerContainer.ContainedEntity != null;
|
||||
[ViewVariables] private ReagentUnit _dispenseAmount = ReagentUnit.New(10);
|
||||
@@ -53,9 +51,14 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
[ViewVariables]
|
||||
private SolutionComponent Solution => _beakerContainer.ContainedEntity.GetComponent<SolutionComponent>();
|
||||
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(ReagentDispenserUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
/// <summary>
|
||||
/// Shows the serializer how to save/load this components yaml prototype.
|
||||
@@ -75,14 +78,19 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(ReagentDispenserUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
_beakerContainer =
|
||||
ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-reagentContainerContainer", Owner);
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
_powerReceiver.OnPowerStateChanged += OnPowerChanged;
|
||||
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged += OnPowerChanged;
|
||||
}
|
||||
|
||||
InitializeFromPrototype();
|
||||
UpdateUserInterface();
|
||||
@@ -108,7 +116,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPowerChanged(object sender, PowerStateEventArgs e)
|
||||
private void OnPowerChanged(object? sender, PowerStateEventArgs e)
|
||||
{
|
||||
UpdateUserInterface();
|
||||
}
|
||||
@@ -120,6 +128,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// <param name="obj">A user interface message from the client.</param>
|
||||
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
if (obj.Session.AttachedEntity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = (UiButtonPressedMessage) obj.Message;
|
||||
var needsPower = msg.Button switch
|
||||
{
|
||||
@@ -175,7 +188,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// </summary>
|
||||
/// <param name="playerEntity">The player entity.</param>
|
||||
/// <returns>Returns true if the entity can use the dispenser, and false if it cannot.</returns>
|
||||
private bool PlayerCanUseDispenser(IEntity playerEntity, bool needsPower = true)
|
||||
private bool PlayerCanUseDispenser(IEntity? playerEntity, bool needsPower = true)
|
||||
{
|
||||
//Need player entity to check if they are still able to use the dispenser
|
||||
if (playerEntity == null)
|
||||
@@ -211,7 +224,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
private void UpdateUserInterface()
|
||||
{
|
||||
var state = GetUserInterfaceState();
|
||||
_userInterface.SetState(state);
|
||||
UserInterface?.SetState(state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -265,12 +278,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// <param name="args">Data relevant to the event such as the actor which triggered it.</param>
|
||||
void IActivate.Activate(ActivateEventArgs args)
|
||||
{
|
||||
if (!args.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!args.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.User.TryGetComponent(out IHandsComponent hands))
|
||||
if (!args.User.TryGetComponent(out IHandsComponent? hands))
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
|
||||
_localizationManager.GetString("You have no hands."));
|
||||
@@ -280,7 +293,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
var activeHandEntity = hands.GetActiveHand?.Owner;
|
||||
if (activeHandEntity == null)
|
||||
{
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,13 +306,20 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
/// <returns></returns>
|
||||
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs args)
|
||||
{
|
||||
if (!args.User.TryGetComponent(out IHandsComponent hands))
|
||||
if (!args.User.TryGetComponent(out IHandsComponent? hands))
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
|
||||
_localizationManager.GetString("You have no hands."));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hands.GetActiveHand == null)
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
|
||||
Loc.GetString("You have nothing on your hand."));
|
||||
return false;
|
||||
}
|
||||
|
||||
var activeHandEntity = hands.GetActiveHand.Owner;
|
||||
if (activeHandEntity.TryGetComponent<SolutionComponent>(out var solution))
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Chemistry;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -11,28 +12,27 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
[RegisterComponent]
|
||||
public class TransformableContainerComponent : Component, ISolutionChange
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override string Name => "TransformableContainer";
|
||||
|
||||
private bool _transformed = false;
|
||||
public bool Transformed { get => _transformed; }
|
||||
private SpriteSpecifier? _initialSprite;
|
||||
private string _initialName = default!;
|
||||
private string _initialDescription = default!;
|
||||
private ReagentPrototype? _currentReagent;
|
||||
|
||||
private SpriteSpecifier _initialSprite;
|
||||
private string _initialName;
|
||||
private string _initialDescription;
|
||||
private SpriteComponent _sprite;
|
||||
|
||||
private ReagentPrototype _currentReagent;
|
||||
public bool Transformed { get; private set; }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_sprite = Owner.GetComponent<SpriteComponent>();
|
||||
_initialSprite = new SpriteSpecifier.Rsi(new ResourcePath(_sprite.BaseRSIPath), "icon");
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite) &&
|
||||
sprite.BaseRSIPath != null)
|
||||
{
|
||||
_initialSprite = new SpriteSpecifier.Rsi(new ResourcePath(sprite.BaseRSIPath), "icon");
|
||||
}
|
||||
|
||||
_initialName = Owner.Name;
|
||||
_initialDescription = Owner.Description;
|
||||
}
|
||||
@@ -40,14 +40,20 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
Owner.GetComponent<SolutionComponent>().Capabilities |= SolutionCaps.FitsInDispenser;;
|
||||
Owner.GetComponent<SolutionComponent>().Capabilities |= SolutionCaps.FitsInDispenser;
|
||||
}
|
||||
|
||||
public void CancelTransformation()
|
||||
{
|
||||
_currentReagent = null;
|
||||
_transformed = false;
|
||||
_sprite.LayerSetSprite(0, _initialSprite);
|
||||
Transformed = false;
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite) &&
|
||||
_initialSprite != null)
|
||||
{
|
||||
sprite.LayerSetSprite(0, _initialSprite);
|
||||
}
|
||||
|
||||
Owner.Name = _initialName;
|
||||
Owner.Description = _initialDescription;
|
||||
}
|
||||
@@ -76,11 +82,16 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
!string.IsNullOrWhiteSpace(proto.SpriteReplacementPath))
|
||||
{
|
||||
var spriteSpec = new SpriteSpecifier.Rsi(new ResourcePath("Objects/Drinks/" + proto.SpriteReplacementPath),"icon");
|
||||
_sprite.LayerSetSprite(0, spriteSpec);
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||
{
|
||||
sprite?.LayerSetSprite(0, spriteSpec);
|
||||
}
|
||||
|
||||
Owner.Name = proto.Name + " glass";
|
||||
Owner.Description = proto.Description;
|
||||
_currentReagent = proto;
|
||||
_transformed = true;
|
||||
Transformed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Components.Command;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -8,6 +9,7 @@ using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Command
|
||||
{
|
||||
@@ -15,22 +17,27 @@ namespace Content.Server.GameObjects.Components.Command
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class CommunicationsConsoleComponent : SharedCommunicationsConsoleComponent, IActivate
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IEntitySystemManager _entitySystemManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
private RoundEndSystem RoundEndSystem => _entitySystemManager.GetEntitySystem<RoundEndSystem>();
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(CommunicationsConsoleUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(CommunicationsConsoleUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
|
||||
RoundEndSystem.OnRoundEndCountdownStarted += UpdateBoundInterface;
|
||||
RoundEndSystem.OnRoundEndCountdownCancelled += UpdateBoundInterface;
|
||||
@@ -39,7 +46,7 @@ namespace Content.Server.GameObjects.Components.Command
|
||||
|
||||
private void UpdateBoundInterface()
|
||||
{
|
||||
_userInterface.SetState(new CommunicationsConsoleInterfaceState(RoundEndSystem.ExpectedCountdownEnd));
|
||||
UserInterface?.SetState(new CommunicationsConsoleInterfaceState(RoundEndSystem.ExpectedCountdownEnd));
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
@@ -58,12 +65,12 @@ namespace Content.Server.GameObjects.Components.Command
|
||||
|
||||
public void OpenUserInterface(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
return;
|
||||
|
||||
if (!Powered)
|
||||
|
||||
@@ -28,10 +28,8 @@ namespace Content.Server.GameObjects.Components.Conveyor
|
||||
[RegisterComponent]
|
||||
public class ConveyorComponent : Component, IInteractUsing
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "Conveyor";
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.Interactable;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.GameObjects.Components.Interactable;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -27,12 +28,6 @@ namespace Content.Server.GameObjects.Components.Damage
|
||||
serializer.DataField(ref _tools, "tools", new List<ToolQuality>());
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
Owner.EnsureComponent<DestructibleComponent>();
|
||||
}
|
||||
|
||||
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Using.TryGetComponent<ToolComponent>(out var tool))
|
||||
@@ -56,7 +51,7 @@ namespace Content.Server.GameObjects.Components.Damage
|
||||
|
||||
protected bool CallDamage(InteractUsingEventArgs eventArgs, ToolComponent tool)
|
||||
{
|
||||
if (eventArgs.Target.TryGetComponent<DestructibleComponent>(out var damageable))
|
||||
if (eventArgs.Target.TryGetComponent<IDamageableComponent>(out var damageable))
|
||||
{
|
||||
damageable.ChangeDamage(tool.HasQuality(ToolQuality.Welding)
|
||||
? DamageType.Heat
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Interfaces;
|
||||
#nullable enable
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Server.Interfaces.GameObjects.Components.Items;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -25,22 +26,24 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
[ComponentReference(typeof(IDisposalTubeComponent))]
|
||||
public class DisposalRouterComponent : DisposalJunctionComponent, IActivate
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
public override string Name => "DisposalRouter";
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
[ViewVariables]
|
||||
private HashSet<string> _tags;
|
||||
private readonly HashSet<string> _tags = new HashSet<string>();
|
||||
|
||||
[ViewVariables]
|
||||
public bool Anchored =>
|
||||
!Owner.TryGetComponent(out CollidableComponent collidable) ||
|
||||
!Owner.TryGetComponent(out ICollidableComponent? collidable) ||
|
||||
collidable.Anchored;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(DisposalRouterUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override Direction NextDirection(DisposalHolderComponent holder)
|
||||
{
|
||||
var directions = ConnectableDirections();
|
||||
@@ -53,15 +56,14 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
return Owner.Transform.LocalRotation.GetDir();
|
||||
}
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(DisposalRouterUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
|
||||
_tags = new HashSet<string>();
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
UpdateUserInterface();
|
||||
}
|
||||
@@ -73,6 +75,11 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
/// <param name="obj">A user interface message from the client.</param>
|
||||
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
if (obj.Session.AttachedEntity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = (UiActionMessage) obj.Message;
|
||||
|
||||
if (!PlayerCanUseDisposalTagger(obj.Session.AttachedEntity))
|
||||
@@ -112,10 +119,10 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
/// <summary>
|
||||
/// Gets component data to be used to update the user interface client-side.
|
||||
/// </summary>
|
||||
/// <returns>Returns a <see cref="SharedDisposalRouterComponent.DisposalRouterBoundUserInterfaceState"/></returns>
|
||||
/// <returns>Returns a <see cref="DisposalRouterUserInterfaceState"/></returns>
|
||||
private DisposalRouterUserInterfaceState GetUserInterfaceState()
|
||||
{
|
||||
if(_tags == null || _tags.Count <= 0)
|
||||
if(_tags.Count <= 0)
|
||||
{
|
||||
return new DisposalRouterUserInterfaceState("");
|
||||
}
|
||||
@@ -136,7 +143,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
private void UpdateUserInterface()
|
||||
{
|
||||
var state = GetUserInterfaceState();
|
||||
_userInterface.SetState(state);
|
||||
UserInterface?.SetState(state);
|
||||
}
|
||||
|
||||
private void ClickSound()
|
||||
@@ -150,12 +157,12 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
/// <param name="args">Data relevant to the event such as the actor which triggered it.</param>
|
||||
void IActivate.Activate(ActivateEventArgs args)
|
||||
{
|
||||
if (!args.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!args.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.User.TryGetComponent(out IHandsComponent hands))
|
||||
if (!args.User.TryGetComponent(out IHandsComponent? hands))
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
|
||||
Loc.GetString("You have no hands."));
|
||||
@@ -166,13 +173,13 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
if (activeHandEntity == null)
|
||||
{
|
||||
UpdateUserInterface();
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
base.OnRemove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Interfaces;
|
||||
#nullable enable
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Server.Interfaces.GameObjects.Components.Items;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -23,35 +24,38 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
[ComponentReference(typeof(IDisposalTubeComponent))]
|
||||
public class DisposalTaggerComponent : DisposalTransitComponent, IActivate
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
public override string Name => "DisposalTagger";
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
private string _tag = "";
|
||||
|
||||
[ViewVariables]
|
||||
public bool Anchored =>
|
||||
!Owner.TryGetComponent(out CollidableComponent collidable) ||
|
||||
!Owner.TryGetComponent(out CollidableComponent? collidable) ||
|
||||
collidable.Anchored;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(DisposalTaggerUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override Direction NextDirection(DisposalHolderComponent holder)
|
||||
{
|
||||
holder.Tags.Add(_tag);
|
||||
return base.NextDirection(holder);
|
||||
}
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(DisposalTaggerUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
UpdateUserInterface();
|
||||
}
|
||||
@@ -81,7 +85,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
/// </summary>
|
||||
/// <param name="playerEntity">The player entity.</param>
|
||||
/// <returns>Returns true if the entity can use the configuration interface, and false if it cannot.</returns>
|
||||
private bool PlayerCanUseDisposalTagger(IEntity playerEntity)
|
||||
private bool PlayerCanUseDisposalTagger(IEntity? playerEntity)
|
||||
{
|
||||
//Need player entity to check if they are still able to use the configuration interface
|
||||
if (playerEntity == null)
|
||||
@@ -98,7 +102,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
/// <summary>
|
||||
/// Gets component data to be used to update the user interface client-side.
|
||||
/// </summary>
|
||||
/// <returns>Returns a <see cref="SharedDisposalTaggerComponent.DisposalTaggerBoundUserInterfaceState"/></returns>
|
||||
/// <returns>Returns a <see cref="DisposalTaggerUserInterfaceState"/></returns>
|
||||
private DisposalTaggerUserInterfaceState GetUserInterfaceState()
|
||||
{
|
||||
return new DisposalTaggerUserInterfaceState(_tag);
|
||||
@@ -107,7 +111,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
private void UpdateUserInterface()
|
||||
{
|
||||
var state = GetUserInterfaceState();
|
||||
_userInterface.SetState(state);
|
||||
UserInterface?.SetState(state);
|
||||
}
|
||||
|
||||
private void ClickSound()
|
||||
@@ -121,12 +125,12 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
/// <param name="args">Data relevant to the event such as the actor which triggered it.</param>
|
||||
void IActivate.Activate(ActivateEventArgs args)
|
||||
{
|
||||
if (!args.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!args.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.User.TryGetComponent(out IHandsComponent hands))
|
||||
if (!args.User.TryGetComponent(out IHandsComponent? hands))
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
|
||||
Loc.GetString("You have no hands."));
|
||||
@@ -137,14 +141,14 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
if (activeHandEntity == null)
|
||||
{
|
||||
UpdateUserInterface();
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
base.OnRemove();
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +39,8 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
[ComponentReference(typeof(IInteractUsing))]
|
||||
public class DisposalUnitComponent : SharedDisposalUnitComponent, IInteractHand, IInteractUsing, IDragDropOn
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "DisposalUnit";
|
||||
|
||||
@@ -81,9 +79,6 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
|
||||
[ViewVariables] public IReadOnlyList<IEntity> ContainedEntities => _container.ContainedEntities;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface _userInterface = default!;
|
||||
|
||||
[ViewVariables]
|
||||
public bool Powered =>
|
||||
!Owner.TryGetComponent(out PowerReceiverComponent? receiver) ||
|
||||
@@ -115,6 +110,13 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(DisposalUnitUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public bool CanInsert(IEntity entity)
|
||||
{
|
||||
if (!Anchored)
|
||||
@@ -161,7 +163,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
|
||||
if (entity.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
_userInterface.Close(actor.playerSession);
|
||||
UserInterface?.Close(actor.playerSession);
|
||||
}
|
||||
|
||||
UpdateVisualState();
|
||||
@@ -291,10 +293,10 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
private void UpdateInterface()
|
||||
{
|
||||
var state = GetInterfaceState();
|
||||
_userInterface.SetState(state);
|
||||
UserInterface?.SetState(state);
|
||||
}
|
||||
|
||||
private bool PlayerCanUse(IEntity player)
|
||||
private bool PlayerCanUse(IEntity? player)
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
@@ -472,9 +474,11 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
base.Initialize();
|
||||
|
||||
_container = ContainerManagerComponent.Ensure<Container>(Name, Owner);
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(DisposalUnitUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
UpdateInterface();
|
||||
}
|
||||
@@ -513,7 +517,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
_container.ForceRemove(entity);
|
||||
}
|
||||
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
|
||||
_automaticEngageToken?.Cancel();
|
||||
_automaticEngageToken = null;
|
||||
@@ -571,7 +575,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
return false;
|
||||
}
|
||||
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.Interactable;
|
||||
@@ -34,10 +35,7 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
/// </summary>
|
||||
private static readonly TimeSpan PowerWiresTimeout = TimeSpan.FromSeconds(5.0);
|
||||
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private WiresComponent _wires;
|
||||
|
||||
private CancellationTokenSource _powerWiresPulsedTimerCancel;
|
||||
private CancellationTokenSource _powerWiresPulsedTimerCancel = new CancellationTokenSource();
|
||||
|
||||
private bool _powerWiresPulsed;
|
||||
|
||||
@@ -89,13 +87,15 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
|
||||
private void UpdateWiresStatus()
|
||||
{
|
||||
WiresComponent? wires;
|
||||
var powerLight = new StatusLightData(Color.Yellow, StatusLightState.On, "POWR");
|
||||
if (PowerWiresPulsed)
|
||||
{
|
||||
powerLight = new StatusLightData(Color.Yellow, StatusLightState.BlinkingFast, "POWR");
|
||||
}
|
||||
else if (_wires.IsWireCut(Wires.MainPower) &&
|
||||
_wires.IsWireCut(Wires.BackupPower))
|
||||
else if (Owner.TryGetComponent(out wires) &&
|
||||
wires.IsWireCut(Wires.MainPower) &&
|
||||
wires.IsWireCut(Wires.BackupPower))
|
||||
{
|
||||
powerLight = new StatusLightData(Color.Red, StatusLightState.On, "POWR");
|
||||
}
|
||||
@@ -114,12 +114,17 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
var safetyStatus =
|
||||
new StatusLightData(Color.Red, Safety ? StatusLightState.On : StatusLightState.Off, "SAFE");
|
||||
|
||||
_wires.SetStatus(AirlockWireStatus.PowerIndicator, powerLight);
|
||||
_wires.SetStatus(AirlockWireStatus.BoltIndicator, boltStatus);
|
||||
_wires.SetStatus(AirlockWireStatus.BoltLightIndicator, boltLightsStatus);
|
||||
_wires.SetStatus(AirlockWireStatus.AIControlIndicator, new StatusLightData(Color.Purple, StatusLightState.BlinkingSlow, "AICT"));
|
||||
_wires.SetStatus(AirlockWireStatus.TimingIndicator, timingStatus);
|
||||
_wires.SetStatus(AirlockWireStatus.SafetyIndicator, safetyStatus);
|
||||
if (!Owner.TryGetComponent(out wires))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wires.SetStatus(AirlockWireStatus.PowerIndicator, powerLight);
|
||||
wires.SetStatus(AirlockWireStatus.BoltIndicator, boltStatus);
|
||||
wires.SetStatus(AirlockWireStatus.BoltLightIndicator, boltLightsStatus);
|
||||
wires.SetStatus(AirlockWireStatus.AIControlIndicator, new StatusLightData(Color.Purple, StatusLightState.BlinkingSlow, "AICT"));
|
||||
wires.SetStatus(AirlockWireStatus.TimingIndicator, timingStatus);
|
||||
wires.SetStatus(AirlockWireStatus.SafetyIndicator, safetyStatus);
|
||||
/*
|
||||
_wires.SetStatus(6, powerLight);
|
||||
_wires.SetStatus(7, powerLight);
|
||||
@@ -131,14 +136,30 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
|
||||
private void UpdatePowerCutStatus()
|
||||
{
|
||||
_powerReceiver.PowerDisabled = PowerWiresPulsed ||
|
||||
_wires.IsWireCut(Wires.MainPower) ||
|
||||
_wires.IsWireCut(Wires.BackupPower);
|
||||
if (!Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PowerWiresPulsed)
|
||||
{
|
||||
receiver.PowerDisabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Owner.TryGetComponent(out WiresComponent? wires))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
receiver.PowerDisabled =
|
||||
wires.IsWireCut(Wires.MainPower) ||
|
||||
wires.IsWireCut(Wires.BackupPower);
|
||||
}
|
||||
|
||||
private void UpdateBoltLightStatus()
|
||||
{
|
||||
if (Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(DoorVisuals.BoltLights, BoltLightsVisible);
|
||||
}
|
||||
@@ -150,7 +171,10 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
{
|
||||
base.State = value;
|
||||
// Only show the maintenance panel if the airlock is closed
|
||||
_wires.IsPanelVisible = value != DoorState.Open;
|
||||
if (Owner.TryGetComponent(out WiresComponent? wires))
|
||||
{
|
||||
wires.IsPanelVisible = value != DoorState.Open;
|
||||
}
|
||||
// If the door is closed, we should look if the bolt was locked while closing
|
||||
UpdateBoltLightStatus();
|
||||
}
|
||||
@@ -159,29 +183,32 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
_wires = Owner.GetComponent<WiresComponent>();
|
||||
|
||||
_powerReceiver.OnPowerStateChanged += PowerDeviceOnOnPowerStateChanged;
|
||||
if (Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
appearance.SetData(DoorVisuals.Powered, _powerReceiver.Powered);
|
||||
receiver.OnPowerStateChanged += PowerDeviceOnOnPowerStateChanged;
|
||||
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
|
||||
appearance.SetData(DoorVisuals.Powered, receiver.Powered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (Owner.TryGetComponent(out _powerReceiver))
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
_powerReceiver.OnPowerStateChanged -= PowerDeviceOnOnPowerStateChanged;
|
||||
receiver.OnPowerStateChanged -= PowerDeviceOnOnPowerStateChanged;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
private void PowerDeviceOnOnPowerStateChanged(object sender, PowerStateEventArgs e)
|
||||
private void PowerDeviceOnOnPowerStateChanged(object? sender, PowerStateEventArgs e)
|
||||
{
|
||||
if (Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(DoorVisuals.Powered, e.Powered);
|
||||
}
|
||||
@@ -192,11 +219,12 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
|
||||
protected override void ActivateImpl(ActivateEventArgs args)
|
||||
{
|
||||
if (_wires.IsPanelOpen)
|
||||
if (Owner.TryGetComponent(out WiresComponent? wires) &&
|
||||
wires.IsPanelOpen)
|
||||
{
|
||||
if (args.User.TryGetComponent(out IActorComponent actor))
|
||||
if (args.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
_wires.OpenInterface(actor.playerSession);
|
||||
wires.OpenInterface(actor.playerSession);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -276,8 +304,7 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
case Wires.MainPower:
|
||||
case Wires.BackupPower:
|
||||
PowerWiresPulsed = true;
|
||||
_powerWiresPulsedTimerCancel?.Cancel();
|
||||
_powerWiresPulsedTimerCancel = new CancellationTokenSource();
|
||||
_powerWiresPulsedTimerCancel.Cancel();
|
||||
Timer.Spawn(PowerWiresTimeout,
|
||||
() => PowerWiresPulsed = false,
|
||||
_powerWiresPulsedTimerCancel.Token);
|
||||
@@ -381,7 +408,8 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
|
||||
private bool IsPowered()
|
||||
{
|
||||
return _powerReceiver.Powered;
|
||||
return !Owner.TryGetComponent(out PowerReceiverComponent? receiver)
|
||||
|| receiver.Powered;
|
||||
}
|
||||
|
||||
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
@@ -392,11 +420,12 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
if (tool.HasQuality(ToolQuality.Cutting)
|
||||
|| tool.HasQuality(ToolQuality.Multitool))
|
||||
{
|
||||
if (_wires.IsPanelOpen)
|
||||
if (Owner.TryGetComponent(out WiresComponent? wires)
|
||||
&& wires.IsPanelOpen)
|
||||
{
|
||||
if (eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
_wires.OpenInterface(actor.playerSession);
|
||||
wires.OpenInterface(actor.playerSession);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Content.Server.GameObjects.Components.Access;
|
||||
@@ -44,10 +45,7 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
protected const float AutoCloseDelay = 5;
|
||||
protected float CloseSpeed = AutoCloseDelay;
|
||||
|
||||
private AirtightComponent airtightComponent;
|
||||
private ICollidableComponent _collidableComponent;
|
||||
private AppearanceComponent _appearance;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
private static readonly TimeSpan CloseTimeOne = TimeSpan.FromSeconds(0.3f);
|
||||
private static readonly TimeSpan CloseTimeTwo = TimeSpan.FromSeconds(0.9f);
|
||||
@@ -68,21 +66,9 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
serializer.DataField(ref _occludes, "occludes", true);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
airtightComponent = Owner.GetComponent<AirtightComponent>();
|
||||
_collidableComponent = Owner.GetComponent<ICollidableComponent>();
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
_cancellationTokenSource?.Cancel();
|
||||
_collidableComponent = null;
|
||||
_appearance = null;
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
@@ -104,7 +90,6 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
ActivateImpl(eventArgs);
|
||||
}
|
||||
|
||||
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
{
|
||||
if (State != DoorState.Closed)
|
||||
@@ -135,8 +120,10 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
|
||||
private void SetAppearance(DoorVisualState state)
|
||||
{
|
||||
if (_appearance != null || Owner.TryGetComponent(out _appearance))
|
||||
_appearance.SetData(DoorVisuals.VisualState, state);
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(DoorVisuals.VisualState, state);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool CanOpen()
|
||||
@@ -147,7 +134,7 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
public bool CanOpen(IEntity user)
|
||||
{
|
||||
if (!CanOpen()) return false;
|
||||
if (!Owner.TryGetComponent(out AccessReader accessReader))
|
||||
if (!Owner.TryGetComponent(out AccessReader? accessReader))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -165,7 +152,7 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
|
||||
Open();
|
||||
|
||||
if (user.TryGetComponent(out HandsComponent hands) && hands.Count == 0)
|
||||
if (user.TryGetComponent(out HandsComponent? hands) && hands.Count == 0)
|
||||
{
|
||||
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/bang.ogg", Owner,
|
||||
AudioParams.Default.WithVolume(-2));
|
||||
@@ -181,15 +168,22 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
|
||||
State = DoorState.Opening;
|
||||
SetAppearance(DoorVisualState.Opening);
|
||||
if (_occludes && Owner.TryGetComponent(out OccluderComponent occluder))
|
||||
if (_occludes && Owner.TryGetComponent(out OccluderComponent? occluder))
|
||||
{
|
||||
occluder.Enabled = false;
|
||||
}
|
||||
|
||||
Timer.Spawn(OpenTimeOne, async () =>
|
||||
{
|
||||
airtightComponent.AirBlocked = false;
|
||||
_collidableComponent.Hard = false;
|
||||
if (Owner.TryGetComponent(out AirtightComponent? airtight))
|
||||
{
|
||||
airtight.AirBlocked = false;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out ICollidableComponent? collidable))
|
||||
{
|
||||
collidable.Hard = false;
|
||||
}
|
||||
|
||||
await Timer.Delay(OpenTimeTwo, _cancellationTokenSource.Token);
|
||||
|
||||
@@ -208,7 +202,7 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
public bool CanClose(IEntity user)
|
||||
{
|
||||
if (!CanClose()) return false;
|
||||
if (!Owner.TryGetComponent(out AccessReader accessReader))
|
||||
if (!Owner.TryGetComponent(out AccessReader? accessReader))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -229,18 +223,22 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
|
||||
private void CheckCrush()
|
||||
{
|
||||
if (!Owner.TryGetComponent(out ICollidableComponent? body))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if collides with something
|
||||
var collidesWith = _collidableComponent.GetCollidingEntities(Vector2.Zero, false);
|
||||
var collidesWith = body.GetCollidingEntities(Vector2.Zero, false);
|
||||
if (collidesWith.Count() != 0)
|
||||
{
|
||||
// Crush
|
||||
bool hitSomeone = false;
|
||||
foreach (var e in collidesWith)
|
||||
{
|
||||
if (!e.TryGetComponent(out StunnableComponent stun)
|
||||
|| !e.TryGetComponent(out IDamageableComponent damage)
|
||||
|| !e.TryGetComponent(out ICollidableComponent otherBody)
|
||||
|| !Owner.TryGetComponent(out ICollidableComponent body))
|
||||
if (!e.TryGetComponent(out StunnableComponent? stun)
|
||||
|| !e.TryGetComponent(out IDamageableComponent? damage)
|
||||
|| !e.TryGetComponent(out ICollidableComponent? otherBody))
|
||||
continue;
|
||||
|
||||
var percentage = otherBody.WorldAABB.IntersectPercentage(body.WorldAABB);
|
||||
@@ -264,7 +262,8 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
public bool Close()
|
||||
{
|
||||
bool shouldCheckCrush = false;
|
||||
if (_collidableComponent.IsColliding(Vector2.Zero, false))
|
||||
|
||||
if (Owner.TryGetComponent(out ICollidableComponent? collidable) && collidable.IsColliding(Vector2.Zero, false))
|
||||
{
|
||||
if (Safety)
|
||||
return false;
|
||||
@@ -276,7 +275,7 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
State = DoorState.Closing;
|
||||
OpenTimeCounter = 0;
|
||||
SetAppearance(DoorVisualState.Closing);
|
||||
if (_occludes && Owner.TryGetComponent(out OccluderComponent occluder))
|
||||
if (_occludes && Owner.TryGetComponent(out OccluderComponent? occluder))
|
||||
{
|
||||
occluder.Enabled = true;
|
||||
}
|
||||
@@ -288,8 +287,15 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
CheckCrush();
|
||||
}
|
||||
|
||||
airtightComponent.AirBlocked = true;
|
||||
_collidableComponent.Hard = true;
|
||||
if (Owner.TryGetComponent(out AirtightComponent? airtight))
|
||||
{
|
||||
airtight.AirBlocked = true;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out ICollidableComponent? body))
|
||||
{
|
||||
body.Hard = true;
|
||||
}
|
||||
|
||||
await Timer.Delay(CloseTimeTwo, _cancellationTokenSource.Token);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.Chemistry;
|
||||
using Content.Shared.Chemistry;
|
||||
@@ -19,23 +20,27 @@ namespace Content.Server.GameObjects.Components.Fluids
|
||||
[RegisterComponent]
|
||||
public class BucketComponent : Component, IInteractUsing
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
|
||||
|
||||
public override string Name => "Bucket";
|
||||
|
||||
public ReagentUnit MaxVolume
|
||||
{
|
||||
get => _contents.MaxVolume;
|
||||
set => _contents.MaxVolume = value;
|
||||
get => Owner.TryGetComponent(out SolutionComponent? solution) ? solution.MaxVolume : ReagentUnit.Zero;
|
||||
set
|
||||
{
|
||||
if (Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
solution.MaxVolume = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ReagentUnit CurrentVolume => _contents.CurrentVolume;
|
||||
public ReagentUnit CurrentVolume => Owner.TryGetComponent(out SolutionComponent? solution)
|
||||
? solution.CurrentVolume
|
||||
: ReagentUnit.Zero;
|
||||
|
||||
private SolutionComponent _contents;
|
||||
|
||||
private string _sound;
|
||||
private string? _sound;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
@@ -47,15 +52,20 @@ namespace Content.Server.GameObjects.Components.Fluids
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_contents = Owner.GetComponent<SolutionComponent>();
|
||||
Owner.EnsureComponent<SolutionComponent>();
|
||||
}
|
||||
|
||||
private bool TryGiveToMop(MopComponent mopComponent)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? contents))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let's fill 'er up
|
||||
// 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 solution = _contents.SplitSolution(transferAmount);
|
||||
var solution = contents.SplitSolution(transferAmount);
|
||||
if (!mopComponent.Contents.TryAddSolution(solution) || mopComponent.CurrentVolume == 0)
|
||||
{
|
||||
return false;
|
||||
@@ -73,7 +83,12 @@ namespace Content.Server.GameObjects.Components.Fluids
|
||||
|
||||
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.Using.TryGetComponent(out MopComponent mopComponent))
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? contents))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!eventArgs.Using.TryGetComponent(out MopComponent? mopComponent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -97,7 +112,7 @@ namespace Content.Server.GameObjects.Components.Fluids
|
||||
}
|
||||
|
||||
var solution = mopComponent.Contents.SplitSolution(transferAmount);
|
||||
if (!_contents.TryAddSolution(solution))
|
||||
if (!contents.TryAddSolution(solution))
|
||||
{
|
||||
//This really shouldn't happen
|
||||
throw new InvalidOperationException();
|
||||
|
||||
@@ -126,18 +126,25 @@ namespace Content.Server.GameObjects.Components.Fluids
|
||||
_contents.Initialize();
|
||||
}
|
||||
|
||||
_snapGrid = Owner.GetComponent<SnapGridComponent>();
|
||||
_snapGrid = Owner.EnsureComponent<SnapGridComponent>();
|
||||
|
||||
// Smaller than 1m^3 for now but realistically this shouldn't be hit
|
||||
MaxVolume = ReagentUnit.New(1000);
|
||||
|
||||
// Random sprite state set server-side so it's consistent across all clients
|
||||
_spriteComponent = Owner.GetComponent<SpriteComponent>();
|
||||
_spriteComponent = Owner.EnsureComponent<SpriteComponent>();
|
||||
|
||||
var robustRandom = IoCManager.Resolve<IRobustRandom>();
|
||||
var randomVariant = robustRandom.Next(0, _spriteVariants - 1);
|
||||
|
||||
if (_spriteComponent.BaseRSIPath != null)
|
||||
{
|
||||
var baseName = new ResourcePath(_spriteComponent.BaseRSIPath).FilenameWithoutExtension;
|
||||
|
||||
_spriteComponent.LayerSetState(0, $"{baseName}-{randomVariant}"); // TODO: Remove hardcode
|
||||
|
||||
}
|
||||
|
||||
// UpdateAppearance should get called soon after this so shouldn't need to call Dirty() here
|
||||
|
||||
UpdateStatus();
|
||||
|
||||
@@ -16,10 +16,9 @@ namespace Content.Server.GameObjects.Components.Fluids
|
||||
[RegisterComponent]
|
||||
class SprayComponent : Component, IAfterInteract
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "Spray";
|
||||
|
||||
private ReagentUnit _transferAmount;
|
||||
|
||||
@@ -37,9 +37,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
[ComponentReference(typeof(ISharedHandsComponent))]
|
||||
public class HandsComponent : SharedHandsComponent, IHandsComponent, IBodyPartAdded, IBodyPartRemoved
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
private string? _activeHand;
|
||||
private uint _nextHand;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_inventory = Owner.GetComponent<InventoryComponent>();
|
||||
_inventory = Owner.EnsureComponent<InventoryComponent>();
|
||||
}
|
||||
|
||||
bool IInventoryController.CanEquip(Slots slot, IEntity entity, bool flagsCheck, out string reason)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Shared.GameObjects.Components.GUI;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Server.GameObjects.Components.UserInterface;
|
||||
@@ -16,7 +15,6 @@ using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
|
||||
|
||||
@@ -25,27 +23,33 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
[RegisterComponent]
|
||||
public sealed class StrippableComponent : SharedStrippableComponent, IDragDrop
|
||||
{
|
||||
[Dependency] private IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
|
||||
public const float StripDelay = 2f;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
private InventoryComponent _inventoryComponent;
|
||||
private HandsComponent _handsComponent;
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(StrippingUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(StrippingUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += HandleUserInterfaceMessage;
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += HandleUserInterfaceMessage;
|
||||
}
|
||||
|
||||
_inventoryComponent = Owner.GetComponent<InventoryComponent>();
|
||||
_handsComponent = Owner.GetComponent<HandsComponent>();
|
||||
Owner.EnsureComponent<InventoryComponent>();
|
||||
Owner.EnsureComponent<HandsComponent>();
|
||||
|
||||
_inventoryComponent.OnItemChanged += UpdateSubscribed;
|
||||
if (Owner.TryGetComponent(out InventoryComponent? inventory))
|
||||
{
|
||||
inventory.OnItemChanged += UpdateSubscribed;
|
||||
}
|
||||
|
||||
// Initial update.
|
||||
UpdateSubscribed();
|
||||
@@ -53,10 +57,15 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
private void UpdateSubscribed()
|
||||
{
|
||||
if (UserInterface == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var inventory = GetInventorySlots();
|
||||
var hands = GetHandSlots();
|
||||
|
||||
_userInterface.SetState(new StrippingBoundUserInterfaceState(inventory, hands));
|
||||
UserInterface.SetState(new StrippingBoundUserInterfaceState(inventory, hands));
|
||||
}
|
||||
|
||||
public bool CanDragDrop(DragDropEventArgs eventArgs)
|
||||
@@ -67,7 +76,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
public bool DragDrop(DragDropEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor)) return false;
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor)) return false;
|
||||
|
||||
OpenUserInterface(actor.playerSession);
|
||||
return true;
|
||||
@@ -77,9 +86,14 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
{
|
||||
var dictionary = new Dictionary<Slots, string>();
|
||||
|
||||
foreach (var slot in _inventoryComponent.Slots)
|
||||
if (!Owner.TryGetComponent(out InventoryComponent? inventory))
|
||||
{
|
||||
dictionary[slot] = _inventoryComponent.GetSlotItem(slot)?.Owner.Name ?? "None";
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
foreach (var slot in inventory.Slots)
|
||||
{
|
||||
dictionary[slot] = inventory.GetSlotItem(slot)?.Owner.Name ?? "None";
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
@@ -89,9 +103,14 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
{
|
||||
var dictionary = new Dictionary<string, string>();
|
||||
|
||||
foreach (var hand in _handsComponent.Hands)
|
||||
if (!Owner.TryGetComponent(out HandsComponent? hands))
|
||||
{
|
||||
dictionary[hand] = _handsComponent.GetItem(hand)?.Owner.Name ?? "None";
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
foreach (var hand in hands.Hands)
|
||||
{
|
||||
dictionary[hand] = hands.GetItem(hand)?.Owner.Name ?? "None";
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
@@ -99,7 +118,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
private void OpenUserInterface(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -336,7 +355,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
private void HandleUserInterfaceMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
var user = obj.Session.AttachedEntity;
|
||||
if (user == null || !(user.TryGetComponent(out HandsComponent userHands))) return;
|
||||
if (user == null || !(user.TryGetComponent(out HandsComponent? userHands))) return;
|
||||
|
||||
var placingItem = userHands.GetActiveHand != null;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Threading.Tasks;
|
||||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.Damage;
|
||||
using Content.Server.GameObjects.Components.Interactable;
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Shared.GameObjects.Components.Gravity;
|
||||
using Content.Shared.GameObjects.Components.Interactable;
|
||||
@@ -22,11 +22,6 @@ namespace Content.Server.GameObjects.Components.Gravity
|
||||
[RegisterComponent]
|
||||
public class GravityGeneratorComponent : SharedGravityGeneratorComponent, IInteractUsing, IBreakAct, IInteractHand
|
||||
{
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
|
||||
private SpriteComponent _sprite;
|
||||
|
||||
private bool _switchedOn;
|
||||
|
||||
@@ -34,7 +29,7 @@ namespace Content.Server.GameObjects.Components.Gravity
|
||||
|
||||
private GravityGeneratorStatus _status;
|
||||
|
||||
public bool Powered => _powerReceiver.Powered;
|
||||
public bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
public bool SwitchedOn => _switchedOn;
|
||||
|
||||
@@ -64,15 +59,21 @@ namespace Content.Server.GameObjects.Components.Gravity
|
||||
|
||||
public override string Name => "GravityGenerator";
|
||||
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(GravityGeneratorUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(GravityGeneratorUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += HandleUIMessage;
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
_sprite = Owner.GetComponent<SpriteComponent>();
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += HandleUIMessage;
|
||||
}
|
||||
|
||||
_switchedOn = true;
|
||||
_intact = true;
|
||||
_status = GravityGeneratorStatus.On;
|
||||
@@ -101,7 +102,7 @@ namespace Content.Server.GameObjects.Components.Gravity
|
||||
|
||||
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.Using.TryGetComponent(out WelderComponent tool))
|
||||
if (!eventArgs.Using.TryGetComponent(out WelderComponent? tool))
|
||||
return false;
|
||||
|
||||
if (!await tool.UseTool(eventArgs.User, Owner, 2f, ToolQuality.Welding, 5f))
|
||||
@@ -150,7 +151,7 @@ namespace Content.Server.GameObjects.Components.Gravity
|
||||
switch (message.Message)
|
||||
{
|
||||
case GeneratorStatusRequestMessage _:
|
||||
_userInterface.SetState(new GeneratorState(Status == GravityGeneratorStatus.On));
|
||||
UserInterface?.SetState(new GeneratorState(Status == GravityGeneratorStatus.On));
|
||||
break;
|
||||
case SwitchGeneratorMessage msg:
|
||||
_switchedOn = msg.On;
|
||||
@@ -163,35 +164,51 @@ namespace Content.Server.GameObjects.Components.Gravity
|
||||
|
||||
private void OpenUserInterface(IPlayerSession playerSession)
|
||||
{
|
||||
_userInterface.Open(playerSession);
|
||||
UserInterface?.Open(playerSession);
|
||||
}
|
||||
|
||||
private void MakeBroken()
|
||||
{
|
||||
_status = GravityGeneratorStatus.Broken;
|
||||
_sprite.LayerSetState(0, "broken");
|
||||
_sprite.LayerSetVisible(1, false);
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||
{
|
||||
sprite.LayerSetState(0, "broken");
|
||||
sprite.LayerSetVisible(1, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeUnpowered()
|
||||
{
|
||||
_status = GravityGeneratorStatus.Unpowered;
|
||||
_sprite.LayerSetState(0, "off");
|
||||
_sprite.LayerSetVisible(1, false);
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||
{
|
||||
sprite.LayerSetState(0, "off");
|
||||
sprite.LayerSetVisible(1, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeOff()
|
||||
{
|
||||
_status = GravityGeneratorStatus.Off;
|
||||
_sprite.LayerSetState(0, "off");
|
||||
_sprite.LayerSetVisible(1, false);
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||
{
|
||||
sprite.LayerSetState(0, "off");
|
||||
sprite.LayerSetVisible(1, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeOn()
|
||||
{
|
||||
_status = GravityGeneratorStatus.On;
|
||||
_sprite.LayerSetState(0, "on");
|
||||
_sprite.LayerSetVisible(1, true);
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||
{
|
||||
sprite.LayerSetState(0, "on");
|
||||
sprite.LayerSetVisible(1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.Interfaces;
|
||||
@@ -34,12 +35,8 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
IUse,
|
||||
IThrown
|
||||
{
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
|
||||
[Dependency] private readonly IGameTiming _gameTiming;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
private static readonly TimeSpan OneSecAgo = TimeSpan.FromSeconds(-1);
|
||||
|
||||
@@ -47,7 +44,7 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
/// The client channel currently playing the instrument, or null if there's none.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
private IPlayerSession _instrumentPlayer;
|
||||
private IPlayerSession? _instrumentPlayer;
|
||||
|
||||
private bool _handheld;
|
||||
|
||||
@@ -72,9 +69,6 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
[ViewVariables]
|
||||
private int _midiEventCount = 0;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the instrument is an item which can be held or not.
|
||||
/// </summary>
|
||||
@@ -95,7 +89,7 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
}
|
||||
}
|
||||
|
||||
public IPlayerSession InstrumentPlayer
|
||||
public IPlayerSession? InstrumentPlayer
|
||||
{
|
||||
get => _instrumentPlayer;
|
||||
private set
|
||||
@@ -108,11 +102,18 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
_instrumentPlayer = value;
|
||||
|
||||
if (value != null)
|
||||
_instrumentPlayer.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||
_instrumentPlayer!.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerStatusChanged(object sender, SessionStatusEventArgs e)
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(InstrumentUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
{
|
||||
if (e.Session != _instrumentPlayer || e.NewStatus != SessionStatus.Disconnected) return;
|
||||
InstrumentPlayer = null;
|
||||
@@ -122,8 +123,11 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(InstrumentUiKey.Key);
|
||||
_userInterface.OnClosed += UserInterfaceOnClosed;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnClosed += UserInterfaceOnClosed;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
@@ -137,14 +141,14 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
return new InstrumentState(Playing, _lastSequencerTick);
|
||||
}
|
||||
|
||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null)
|
||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession? session = null)
|
||||
{
|
||||
base.HandleNetworkMessage(message, channel, session);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case InstrumentMidiEventMessage midiEventMsg:
|
||||
if (!Playing || session != _instrumentPlayer) return;
|
||||
if (!Playing || session != _instrumentPlayer || InstrumentPlayer == null) return;
|
||||
|
||||
var send = true;
|
||||
|
||||
@@ -231,7 +235,7 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
Clean();
|
||||
SendNetworkMessage(new InstrumentStopMidiMessage());
|
||||
InstrumentPlayer = null;
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
}
|
||||
|
||||
public void Thrown(ThrownEventArgs eventArgs)
|
||||
@@ -239,7 +243,7 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
Clean();
|
||||
SendNetworkMessage(new InstrumentStopMidiMessage());
|
||||
InstrumentPlayer = null;
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
}
|
||||
|
||||
public void HandSelected(HandSelectedEventArgs eventArgs)
|
||||
@@ -255,12 +259,12 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
{
|
||||
Clean();
|
||||
SendNetworkMessage(new InstrumentStopMidiMessage());
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
}
|
||||
|
||||
public void Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (Handheld || !eventArgs.User.TryGetComponent(out IActorComponent actor)) return;
|
||||
if (Handheld || !eventArgs.User.TryGetComponent(out IActorComponent? actor)) return;
|
||||
|
||||
if (InstrumentPlayer != null) return;
|
||||
|
||||
@@ -270,7 +274,7 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
|
||||
public bool UseEntity(UseEntityEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor)) return false;
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor)) return false;
|
||||
|
||||
if (InstrumentPlayer == actor.playerSession)
|
||||
{
|
||||
@@ -291,7 +295,7 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
|
||||
private void OpenUserInterface(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
public override void Update(float delta)
|
||||
@@ -302,7 +306,7 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
{
|
||||
InstrumentPlayer = null;
|
||||
Clean();
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
}
|
||||
|
||||
if ((_batchesDropped >= MaxMidiBatchDropped
|
||||
@@ -314,9 +318,9 @@ namespace Content.Server.GameObjects.Components.Instruments
|
||||
SendNetworkMessage(new InstrumentStopMidiMessage());
|
||||
Playing = false;
|
||||
|
||||
_userInterface.CloseAll();
|
||||
UserInterface?.CloseAll();
|
||||
|
||||
if (mob.TryGetComponent(out StunnableComponent stun))
|
||||
if (mob != null && mob.TryGetComponent(out StunnableComponent? stun))
|
||||
{
|
||||
stun.Stun(1);
|
||||
Clean();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
using Content.Server.GameObjects.Components.Items.Clothing;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
@@ -29,25 +30,20 @@ namespace Content.Server.GameObjects.Components.Interactable
|
||||
[RegisterComponent]
|
||||
internal sealed class HandheldLightComponent : SharedHandheldLightComponent, IUse, IExamine, IInteractUsing, IMapInit
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ISharedNotifyManager _notifyManager;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly ISharedNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] public float Wattage { get; set; } = 10;
|
||||
[ViewVariables] private ContainerSlot _cellContainer;
|
||||
private PointLightComponent _pointLight;
|
||||
private SpriteComponent _spriteComponent;
|
||||
private ClothingComponent _clothingComponent;
|
||||
[ViewVariables] private ContainerSlot _cellContainer = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private BatteryComponent Cell
|
||||
private BatteryComponent? Cell
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_cellContainer.ContainedEntity == null) return null;
|
||||
|
||||
_cellContainer.ContainedEntity.TryGetComponent(out BatteryComponent cell);
|
||||
_cellContainer.ContainedEntity.TryGetComponent(out BatteryComponent? cell);
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
@@ -98,11 +94,10 @@ namespace Content.Server.GameObjects.Components.Interactable
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_pointLight = Owner.GetComponent<PointLightComponent>();
|
||||
_spriteComponent = Owner.GetComponent<SpriteComponent>();
|
||||
Owner.TryGetComponent(out _clothingComponent);
|
||||
Owner.EnsureComponent<PointLightComponent>();
|
||||
_cellContainer =
|
||||
ContainerManagerComponent.Ensure<ContainerSlot>("flashlight_cell_container", Owner, out _);
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
@@ -179,11 +174,19 @@ namespace Content.Server.GameObjects.Components.Interactable
|
||||
|
||||
private void SetState(bool on)
|
||||
{
|
||||
_spriteComponent.LayerSetVisible(1, on);
|
||||
_pointLight.Enabled = on;
|
||||
if (_clothingComponent != null)
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||
{
|
||||
_clothingComponent.ClothingEquippedPrefix = on ? "On" : "Off";
|
||||
sprite.LayerSetVisible(1, on);
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out PointLightComponent? light))
|
||||
{
|
||||
light.Enabled = on;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out ClothingComponent? clothing))
|
||||
{
|
||||
clothing.ClothingEquippedPrefix = on ? "On" : "Off";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +214,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
||||
return;
|
||||
}
|
||||
|
||||
if (!user.TryGetComponent(out HandsComponent hands))
|
||||
if (!user.TryGetComponent(out HandsComponent? hands))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,10 +29,8 @@ namespace Content.Server.GameObjects.Components.Interactable
|
||||
[ComponentReference(typeof(IToolComponent))]
|
||||
public class WelderComponent : ToolComponent, IExamine, IUse, ISuicideAct, ISolutionChange
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "Welder";
|
||||
public override uint? NetID => ContentNetIDs.WELDER;
|
||||
|
||||
@@ -21,10 +21,8 @@ namespace Content.Server.GameObjects.Components.Items
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "FloorTile";
|
||||
private StackComponent _stack;
|
||||
private string _outputTile;
|
||||
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
@@ -34,18 +32,20 @@ namespace Content.Server.GameObjects.Components.Items
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_stack = Owner.GetComponent<StackComponent>();
|
||||
Owner.EnsureComponent<StackComponent>();
|
||||
}
|
||||
|
||||
public void AfterInteract(AfterInteractEventArgs eventArgs)
|
||||
{
|
||||
if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return;
|
||||
if (!Owner.TryGetComponent(out StackComponent stack)) return;
|
||||
|
||||
var attacked = eventArgs.Target;
|
||||
var mapGrid = _mapManager.GetGrid(eventArgs.ClickLocation.GridID);
|
||||
var tile = mapGrid.GetTileRef(eventArgs.ClickLocation);
|
||||
var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId];
|
||||
|
||||
if (tileDef.IsSubFloor && attacked == null && _stack.Use(1))
|
||||
if (tileDef.IsSubFloor && attacked == null && stack.Use(1))
|
||||
{
|
||||
var desiredTile = _tileDefinitionManager[_outputTile];
|
||||
mapGrid.SetTile(eventArgs.ClickLocation, new Tile(desiredTile.TileId));
|
||||
|
||||
@@ -37,10 +37,8 @@ namespace Content.Server.GameObjects.Components.Items.Storage
|
||||
public class ServerStorageComponent : SharedStorageComponent, IInteractUsing, IUse, IActivate, IStorageComponent, IDestroyAct, IExAct,
|
||||
IDragDrop
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
private const string LoggerName = "Storage";
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -39,25 +40,19 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class MicrowaveComponent : SharedMicrowaveComponent, IActivate, IInteractUsing, ISolutionChange, ISuicideAct
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntityManager _entityManager;
|
||||
[Dependency] private readonly RecipeManager _recipeManager;
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly RecipeManager _recipeManager = default!;
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
|
||||
#region YAMLSERIALIZE
|
||||
private int _cookTimeDefault;
|
||||
private int _cookTimeMultiplier; //For upgrades and stuff I guess?
|
||||
private string _badRecipeName;
|
||||
private string _startCookingSound;
|
||||
private string _cookingCompleteSound;
|
||||
private string _badRecipeName = "";
|
||||
private string _startCookingSound = "";
|
||||
private string _cookingCompleteSound = "";
|
||||
#endregion
|
||||
|
||||
#region VIEWVARIABLES
|
||||
[ViewVariables]
|
||||
private SolutionComponent _solution;
|
||||
|
||||
[ViewVariables]
|
||||
[ViewVariables]
|
||||
private bool _busy = false;
|
||||
|
||||
/// <summary>
|
||||
@@ -67,20 +62,23 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
private uint _currentCookTimerTime = 1;
|
||||
#endregion
|
||||
|
||||
private bool _powered => _powerReceiver.Powered;
|
||||
private bool _hasContents => _solution.ReagentList.Count > 0 || _storage.ContainedEntities.Count > 0;
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
private bool _hasContents => Owner.TryGetComponent(out SolutionComponent? solution) && (solution.ReagentList.Count > 0 || _storage.ContainedEntities.Count > 0);
|
||||
private bool _uiDirty = true;
|
||||
private bool _lostPower = false;
|
||||
private int _currentCookTimeButtonIndex = 0;
|
||||
|
||||
void ISolutionChange.SolutionChanged(SolutionChangeEventArgs eventArgs) => _uiDirty = true;
|
||||
private AudioSystem _audioSystem;
|
||||
private AppearanceComponent _appearance;
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private BoundUserInterface _userInterface;
|
||||
private Container _storage;
|
||||
private AudioSystem _audioSystem = default!;
|
||||
private Container _storage = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(MicrowaveUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
@@ -95,22 +93,21 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_solution ??= Owner.TryGetComponent(out SolutionComponent solutionComponent)
|
||||
? solutionComponent
|
||||
: Owner.AddComponent<SolutionComponent>();
|
||||
|
||||
Owner.EnsureComponent<SolutionComponent>();
|
||||
|
||||
_storage = ContainerManagerComponent.Ensure<Container>("microwave_entity_container", Owner, out var existed);
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
_audioSystem = EntitySystem.Get<AudioSystem>();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(MicrowaveUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage message)
|
||||
{
|
||||
if (!_powered || _busy)
|
||||
if (!Powered || _busy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -158,13 +155,13 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
public void OnUpdate()
|
||||
{
|
||||
|
||||
if (!_powered)
|
||||
if (!Powered)
|
||||
{
|
||||
//TODO:If someone cuts power currently, microwave magically keeps going. FIX IT!
|
||||
SetAppearance(MicrowaveVisualState.Idle);
|
||||
}
|
||||
|
||||
if (_busy && !_powered)
|
||||
if (_busy && !Powered)
|
||||
{
|
||||
//we lost power while we were cooking/busy!
|
||||
_lostPower = true;
|
||||
@@ -174,11 +171,11 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
_uiDirty = true;
|
||||
}
|
||||
|
||||
if (_uiDirty)
|
||||
if (_uiDirty && Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
_userInterface.SetState(new MicrowaveUpdateUserInterfaceState
|
||||
UserInterface?.SetState(new MicrowaveUpdateUserInterfaceState
|
||||
(
|
||||
_solution.Solution.Contents.ToArray(),
|
||||
solution.Solution.Contents.ToArray(),
|
||||
_storage.ContainedEntities.Select(item => item.Uid).ToArray(),
|
||||
_busy,
|
||||
_currentCookTimeButtonIndex,
|
||||
@@ -190,26 +187,26 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
|
||||
private void SetAppearance(MicrowaveVisualState state)
|
||||
{
|
||||
if (_appearance != null || Owner.TryGetComponent(out _appearance))
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
_appearance.SetData(PowerDeviceVisuals.VisualState, state);
|
||||
appearance.SetData(PowerDeviceVisuals.VisualState, state);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor) || !_powered)
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor) || !Powered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_uiDirty = true;
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
|
||||
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
{
|
||||
if (!_powered)
|
||||
if (!Powered)
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
|
||||
Loc.GetString("It has no power!"));
|
||||
@@ -232,8 +229,13 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//Get transfer amount. May be smaller than _transferAmount if not enough room
|
||||
var realTransferAmount = ReagentUnit.Min(attackPourable.TransferAmount, _solution.EmptyVolume);
|
||||
var realTransferAmount = ReagentUnit.Min(attackPourable.TransferAmount, solution.EmptyVolume);
|
||||
if (realTransferAmount <= 0) //Special message if container is full
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
|
||||
@@ -243,7 +245,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
|
||||
//Move units from attackSolution to targetSolution
|
||||
var removedSolution = attackSolution.SplitSolution(realTransferAmount);
|
||||
if (!_solution.TryAddSolution(removedSolution))
|
||||
if (!solution.TryAddSolution(removedSolution))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -280,6 +282,11 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
var solidsDict = new Dictionary<string, int>();
|
||||
foreach(var item in _storage.ContainedEntities)
|
||||
{
|
||||
if (item.Prototype == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(solidsDict.ContainsKey(item.Prototype.ID))
|
||||
{
|
||||
solidsDict[item.Prototype.ID]++;
|
||||
@@ -303,7 +310,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
}
|
||||
|
||||
// Check recipes
|
||||
FoodRecipePrototype recipeToCook = null;
|
||||
FoodRecipePrototype? recipeToCook = null;
|
||||
foreach (var r in _recipeManager.Recipes.Where(r => CanSatisfyRecipe(r, solidsDict) == MicrowaveSuccessState.RecipePass))
|
||||
{
|
||||
recipeToCook = r;
|
||||
@@ -330,7 +337,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
{
|
||||
if (goodMeal)
|
||||
{
|
||||
SubtractContents(recipeToCook);
|
||||
SubtractContents(recipeToCook!);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -357,12 +364,18 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
|
||||
private void VaporizeReagents()
|
||||
{
|
||||
_solution.RemoveAllSolution();
|
||||
if (Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
solution.RemoveAllSolution();
|
||||
}
|
||||
}
|
||||
|
||||
private void VaporizeReagentQuantity(Solution.ReagentQuantity reagentQuantity)
|
||||
{
|
||||
_solution.TryRemoveReagent(reagentQuantity.ReagentId, reagentQuantity.Quantity);
|
||||
if (Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
solution?.TryRemoveReagent(reagentQuantity.ReagentId, reagentQuantity.Quantity);
|
||||
}
|
||||
}
|
||||
|
||||
private void VaporizeSolids()
|
||||
@@ -395,9 +408,14 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
|
||||
private void SubtractContents(FoodRecipePrototype recipe)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(var recipeReagent in recipe.IngredientsReagents)
|
||||
{
|
||||
_solution.TryRemoveReagent(recipeReagent.Key, ReagentUnit.New(recipeReagent.Value));
|
||||
solution?.TryRemoveReagent(recipeReagent.Key, ReagentUnit.New(recipeReagent.Value));
|
||||
}
|
||||
|
||||
foreach (var recipeSolid in recipe.IngredientsSolids)
|
||||
@@ -406,6 +424,11 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
{
|
||||
foreach (var item in _storage.ContainedEntities)
|
||||
{
|
||||
if (item.Prototype == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.Prototype.ID == recipeSolid.Key)
|
||||
{
|
||||
_storage.Remove(item);
|
||||
@@ -420,9 +443,14 @@ namespace Content.Server.GameObjects.Components.Kitchen
|
||||
|
||||
private MicrowaveSuccessState CanSatisfyRecipe(FoodRecipePrototype recipe, Dictionary<string,int> solids)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
return MicrowaveSuccessState.RecipeFail;
|
||||
}
|
||||
|
||||
foreach (var reagent in recipe.IngredientsReagents)
|
||||
{
|
||||
if (!_solution.ContainsReagent(reagent.Key, out var amount))
|
||||
if (!solution.ContainsReagent(reagent.Key, out var amount))
|
||||
{
|
||||
return MicrowaveSuccessState.RecipeFail;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
using Content.Shared.Interfaces;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -8,6 +9,7 @@ using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components
|
||||
{
|
||||
@@ -15,19 +17,41 @@ namespace Content.Server.GameObjects.Components
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class MagicMirrorComponent : SharedMagicMirrorComponent, IActivate
|
||||
{
|
||||
private BoundUserInterface _userInterface;
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(MagicMirrorUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(MagicMirrorUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage -= OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
private static void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
if (!obj.Session.AttachedEntity.TryGetComponent(out HumanoidAppearanceComponent looks))
|
||||
if (obj.Session.AttachedEntity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj.Session.AttachedEntity.TryGetComponent(out HumanoidAppearanceComponent? looks))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -70,23 +94,23 @@ namespace Content.Server.GameObjects.Components
|
||||
|
||||
public void Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!eventArgs.User.TryGetComponent(out HumanoidAppearanceComponent looks))
|
||||
if (!eventArgs.User.TryGetComponent(out HumanoidAppearanceComponent? looks))
|
||||
{
|
||||
Owner.PopupMessage(eventArgs.User, Loc.GetString("You can't have any hair!"));
|
||||
return;
|
||||
}
|
||||
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
|
||||
var msg = new MagicMirrorInitialDataMessage(looks.Appearance.HairColor, looks.Appearance.FacialHairColor, looks.Appearance.HairStyleName,
|
||||
looks.Appearance.FacialHairStyleName);
|
||||
|
||||
_userInterface.SendMessage(msg, actor.playerSession);
|
||||
UserInterface?.SendMessage(msg, actor.playerSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
@@ -16,6 +17,7 @@ using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Medical
|
||||
{
|
||||
@@ -23,29 +25,34 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class MedicalScannerComponent : SharedMedicalScannerComponent, IActivate
|
||||
{
|
||||
private AppearanceComponent _appearance;
|
||||
private BoundUserInterface _userInterface;
|
||||
private ContainerSlot _bodyContainer;
|
||||
private ContainerSlot _bodyContainer = default!;
|
||||
private readonly Vector2 _ejectOffset = new Vector2(-0.5f, 0f);
|
||||
public bool IsOccupied => _bodyContainer.ContainedEntity != null;
|
||||
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
[ViewVariables]
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(MedicalScannerUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(MedicalScannerUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
_bodyContainer = ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-bodyContainer", Owner);
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
//TODO: write this so that it checks for a change in power events and acts accordingly.
|
||||
_bodyContainer = ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-bodyContainer", Owner);
|
||||
|
||||
// TODO: write this so that it checks for a change in power events and acts accordingly.
|
||||
var newState = GetUserInterfaceState();
|
||||
_userInterface.SetState(newState);
|
||||
UserInterface?.SetState(newState);
|
||||
|
||||
UpdateUserInterface();
|
||||
}
|
||||
@@ -62,11 +69,15 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
var body = _bodyContainer.ContainedEntity;
|
||||
if (body == null)
|
||||
{
|
||||
_appearance.SetData(MedicalScannerVisuals.Status, MedicalScannerStatus.Open);
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance?.SetData(MedicalScannerVisuals.Status, MedicalScannerStatus.Open);
|
||||
};
|
||||
|
||||
return EmptyUIState;
|
||||
}
|
||||
|
||||
if (!body.TryGetComponent(out IDamageableComponent damageable) ||
|
||||
if (!body.TryGetComponent(out IDamageableComponent? damageable) ||
|
||||
damageable.CurrentDamageState == DamageState.Dead)
|
||||
{
|
||||
return EmptyUIState;
|
||||
@@ -86,7 +97,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
}
|
||||
|
||||
var newState = GetUserInterfaceState();
|
||||
_userInterface.SetState(newState);
|
||||
UserInterface?.SetState(newState);
|
||||
}
|
||||
|
||||
private MedicalScannerStatus GetStatusFromDamageState(DamageState damageState)
|
||||
@@ -115,12 +126,15 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
|
||||
private void UpdateAppearance()
|
||||
{
|
||||
_appearance.SetData(MedicalScannerVisuals.Status, GetStatus());
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(MedicalScannerVisuals.Status, GetStatus());
|
||||
}
|
||||
}
|
||||
|
||||
public void Activate(ActivateEventArgs args)
|
||||
{
|
||||
if (!args.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!args.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -128,7 +142,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
if (!Powered)
|
||||
return;
|
||||
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
|
||||
[Verb]
|
||||
|
||||
@@ -27,7 +27,8 @@ namespace Content.Server.GameObjects.Components.Mining
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
var spriteComponent = Owner.GetComponent<SpriteComponent>();
|
||||
|
||||
var spriteComponent = Owner.EnsureComponent<SpriteComponent>();
|
||||
spriteComponent.LayerSetState(0, _random.Pick(SpriteStates));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.EntitySystems.AI;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.EntitySystems.AI;
|
||||
using Content.Shared.GameObjects.Components.Movement;
|
||||
using Robust.Server.AI;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -14,23 +15,23 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
[RegisterComponent, ComponentReference(typeof(IMoverComponent))]
|
||||
public class AiControllerComponent : Component, IMoverComponent
|
||||
{
|
||||
private string _logicName;
|
||||
private string? _logicName;
|
||||
private float _visionRadius;
|
||||
|
||||
public override string Name => "AiController";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string LogicName
|
||||
public string? LogicName
|
||||
{
|
||||
get => _logicName;
|
||||
set
|
||||
{
|
||||
_logicName = value;
|
||||
Processor = null;
|
||||
Processor = null!;
|
||||
}
|
||||
}
|
||||
|
||||
public AiLogicProcessor Processor { get; set; }
|
||||
public AiLogicProcessor? Processor { get; set; }
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float VisionRadius
|
||||
@@ -45,8 +46,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
base.Initialize();
|
||||
|
||||
// This component requires a collidable component.
|
||||
if (!Owner.HasComponent<ICollidableComponent>())
|
||||
Owner.AddComponent<CollidableComponent>();
|
||||
Owner.EnsureComponent<CollidableComponent>();
|
||||
|
||||
EntitySystem.Get<AiSystem>().ProcessorInitialize(this);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent component))
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent? component))
|
||||
{
|
||||
return component.CurrentWalkSpeed;
|
||||
}
|
||||
@@ -91,7 +91,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent component))
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent? component))
|
||||
{
|
||||
return component.CurrentSprintSpeed;
|
||||
}
|
||||
|
||||
@@ -24,10 +24,8 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
[ComponentReference(typeof(IClimbable))]
|
||||
public class ClimbableComponent : SharedClimbableComponent, IDragDropOn
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
/// <summary>
|
||||
/// The range from which this entity can be climbed.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.GameObjects.Components.Movement;
|
||||
using Robust.Server.GameObjects;
|
||||
@@ -18,9 +19,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
[RegisterComponent]
|
||||
public class ServerPortalComponent : SharedPortalComponent
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerEntityManager _serverEntityManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
|
||||
|
||||
// Potential improvements: Different sounds,
|
||||
// Add Gateways
|
||||
@@ -28,15 +27,14 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
// Put portal above most other things layer-wise
|
||||
// Add telefragging (get entities on connecting portal and force brute damage)
|
||||
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
private IEntity _connectingTeleporter;
|
||||
private IEntity? _connectingTeleporter;
|
||||
private PortalState _state = PortalState.Pending;
|
||||
[ViewVariables(VVAccess.ReadWrite)] private float _individualPortalCooldown;
|
||||
[ViewVariables] private float _overallPortalCooldown;
|
||||
[ViewVariables] private bool _onCooldown;
|
||||
[ViewVariables] private string _departureSound;
|
||||
[ViewVariables] private string _arrivalSound;
|
||||
public List<IEntity> immuneEntities = new List<IEntity>(); // K
|
||||
[ViewVariables] private string _departureSound = "";
|
||||
[ViewVariables] private string _arrivalSound = "";
|
||||
public readonly List<IEntity> ImmuneEntities = new List<IEntity>(); // K
|
||||
[ViewVariables(VVAccess.ReadWrite)] private float _aliveTime;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
@@ -52,12 +50,6 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
serializer.DataField(ref _arrivalSound, "arrival_sound", "/Audio/Effects/teleport_arrival.ogg");
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_appearanceComponent = Owner.GetComponent<AppearanceComponent>();
|
||||
}
|
||||
|
||||
public override void OnAdd()
|
||||
{
|
||||
// This will blow up an entity it's attached to
|
||||
@@ -74,13 +66,6 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
_appearanceComponent = null;
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
public bool CanBeConnected()
|
||||
{
|
||||
if (_connectingTeleporter == null)
|
||||
@@ -108,23 +93,24 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
}
|
||||
|
||||
_state = targetState;
|
||||
if (_appearanceComponent != null)
|
||||
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
_appearanceComponent.SetData(PortalVisuals.State, _state);
|
||||
appearance.SetData(PortalVisuals.State, _state);
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseCooldown(IEntity entity)
|
||||
private void ReleaseCooldown(IEntity entity)
|
||||
{
|
||||
if (immuneEntities.Contains(entity))
|
||||
if (ImmuneEntities.Contains(entity))
|
||||
{
|
||||
immuneEntities.Remove(entity);
|
||||
ImmuneEntities.Remove(entity);
|
||||
}
|
||||
|
||||
if (_connectingTeleporter != null &&
|
||||
_connectingTeleporter.TryGetComponent<ServerPortalComponent>(out var otherPortal))
|
||||
{
|
||||
otherPortal.immuneEntities.Remove(entity);
|
||||
otherPortal.ImmuneEntities.Remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +128,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
private bool IsEntityPortable(IEntity entity)
|
||||
{
|
||||
// TODO: Check if it's slotted etc. Otherwise the slot item itself gets ported.
|
||||
if (!immuneEntities.Contains(entity) && entity.HasComponent<TeleportableComponent>())
|
||||
if (!ImmuneEntities.Contains(entity) && entity.HasComponent<TeleportableComponent>())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -192,7 +178,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
|
||||
public void TryPortalEntity(IEntity entity)
|
||||
{
|
||||
if (immuneEntities.Contains(entity) || _connectingTeleporter == null)
|
||||
if (ImmuneEntities.Contains(entity) || _connectingTeleporter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -208,9 +194,9 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
soundPlayer.PlayAtCoords(_arrivalSound, entity.Transform.GridPosition);
|
||||
TryChangeState(PortalState.RecentlyTeleported);
|
||||
// To stop spam teleporting. Could potentially look at adding a timer to flush this from the portal
|
||||
immuneEntities.Add(entity);
|
||||
_connectingTeleporter.GetComponent<ServerPortalComponent>().immuneEntities.Add(entity);
|
||||
Timer.Spawn(TimeSpan.FromSeconds(_individualPortalCooldown), () => releaseCooldown(entity));
|
||||
ImmuneEntities.Add(entity);
|
||||
_connectingTeleporter.GetComponent<ServerPortalComponent>().ImmuneEntities.Add(entity);
|
||||
Timer.Spawn(TimeSpan.FromSeconds(_individualPortalCooldown), () => ReleaseCooldown(entity));
|
||||
StartCooldown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Shared.GameObjects.Components.Movement;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -24,11 +25,10 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
[RegisterComponent]
|
||||
public class ServerTeleporterComponent : Component, IAfterInteract
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IMapManager _mapManager;
|
||||
[Dependency] private readonly IServerEntityManager _serverEntityManager;
|
||||
[Dependency] private readonly IRobustRandom _spreadRandom;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _spreadRandom = default!;
|
||||
|
||||
// TODO: Look at MapManager.Map for Beacons to get all entities on grid
|
||||
public ItemTeleporterState State => _state;
|
||||
|
||||
@@ -39,15 +39,13 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
[ViewVariables] private int _range;
|
||||
[ViewVariables] private ItemTeleporterState _state;
|
||||
[ViewVariables] private TeleporterType _teleporterType;
|
||||
[ViewVariables] private string _departureSound;
|
||||
[ViewVariables] private string _arrivalSound;
|
||||
[ViewVariables] private string _cooldownSound;
|
||||
[ViewVariables] private string _departureSound = "";
|
||||
[ViewVariables] private string _arrivalSound = "";
|
||||
[ViewVariables] private string? _cooldownSound;
|
||||
// If the direct OR random teleport will try to avoid hitting collidables
|
||||
[ViewVariables] private bool _avoidCollidable;
|
||||
[ViewVariables] private float _portalAliveTime;
|
||||
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
@@ -63,22 +61,20 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
serializer.DataField(ref _portalAliveTime, "portal_alive_time", 5.0f); // TODO: Change this to 0 before PR?
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
_appearanceComponent = null;
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
private void SetState(ItemTeleporterState newState)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (newState == ItemTeleporterState.Cooldown)
|
||||
{
|
||||
_appearanceComponent.SetData(TeleporterVisuals.VisualState, TeleporterVisualState.Charging);
|
||||
appearance.SetData(TeleporterVisuals.VisualState, TeleporterVisualState.Charging);
|
||||
}
|
||||
else
|
||||
{
|
||||
_appearanceComponent.SetData(TeleporterVisuals.VisualState, TeleporterVisualState.Ready);
|
||||
appearance.SetData(TeleporterVisuals.VisualState, TeleporterVisualState.Ready);
|
||||
}
|
||||
_state = newState;
|
||||
}
|
||||
@@ -149,12 +145,11 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_appearanceComponent = Owner.GetComponent<AppearanceComponent>();
|
||||
_state = ItemTeleporterState.Off;
|
||||
base.Initialize();
|
||||
_state = ItemTeleporterState.Off;
|
||||
}
|
||||
|
||||
private bool emptySpace(IEntity user, Vector2 target)
|
||||
private bool EmptySpace(IEntity user, Vector2 target)
|
||||
{
|
||||
// TODO: Check the user's spot? Upside is no stacking TPs but downside is they can't unstuck themselves from walls.
|
||||
foreach (var entity in _serverEntityManager.GetEntitiesIntersecting(user.Transform.MapID, target))
|
||||
@@ -167,7 +162,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
return true;
|
||||
}
|
||||
|
||||
private Vector2 randomEmptySpot(IEntity user, int range)
|
||||
private Vector2 RandomEmptySpot(IEntity user, int range)
|
||||
{
|
||||
Vector2 targetVector = user.Transform.GridPosition.Position;
|
||||
// Definitely a better way to do this
|
||||
@@ -176,7 +171,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
var randomRange = _spreadRandom.Next(0, range);
|
||||
var angle = Angle.FromDegrees(_spreadRandom.Next(0, 359));
|
||||
targetVector = user.Transform.GridPosition.Position + angle.ToVec() * randomRange;
|
||||
if (emptySpace(user, targetVector))
|
||||
if (EmptySpace(user, targetVector))
|
||||
{
|
||||
return targetVector;
|
||||
}
|
||||
@@ -200,7 +195,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
Vector2 targetVector;
|
||||
if (_avoidCollidable)
|
||||
{
|
||||
targetVector = randomEmptySpot(user, _range);
|
||||
targetVector = RandomEmptySpot(user, _range);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -227,7 +222,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
public void Teleport(IEntity user, Vector2 vector)
|
||||
{
|
||||
// Messy maybe?
|
||||
GridCoordinates targetGrid = new GridCoordinates(vector, user.Transform.GridID);
|
||||
var targetGrid = new GridCoordinates(vector, user.Transform.GridID);
|
||||
var soundPlayer = EntitySystem.Get<AudioSystem>();
|
||||
|
||||
// If portals use those, otherwise just move em over
|
||||
@@ -240,11 +235,12 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
|
||||
// Arrival portal
|
||||
var arrivalPortal = _serverEntityManager.SpawnEntity("Portal", targetGrid);
|
||||
arrivalPortal.TryGetComponent<ServerPortalComponent>(out var arrivalComponent);
|
||||
|
||||
if (arrivalPortal.TryGetComponent<ServerPortalComponent>(out var arrivalComponent))
|
||||
{
|
||||
// Connect. TODO: If the OnUpdate in ServerPortalComponent is changed this may need to change as well.
|
||||
arrivalComponent.TryConnectPortal(departurePortal);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Departure
|
||||
|
||||
@@ -22,10 +22,8 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
[ComponentReference(typeof(IMoverComponent))]
|
||||
internal class ShuttleControllerComponent : Component, IMoverComponent
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
private bool _movingUp;
|
||||
private bool _movingDown;
|
||||
|
||||
@@ -48,7 +48,12 @@ namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups
|
||||
|
||||
public void AddApc(ApcComponent apc)
|
||||
{
|
||||
_apcBatteries.Add(apc, apc.Battery);
|
||||
if (!apc.Owner.TryGetComponent(out BatteryComponent battery))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_apcBatteries.Add(apc, battery);
|
||||
}
|
||||
|
||||
public void RemoveApc(ApcComponent apc)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.GameObjects.Components.Body.Digestive;
|
||||
using Content.Server.GameObjects.Components.Chemistry;
|
||||
@@ -25,24 +26,30 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
||||
[ComponentReference(typeof(IAfterInteract))]
|
||||
public class FoodComponent : Component, IUse, IAfterInteract
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystem;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
|
||||
|
||||
public override string Name => "Food";
|
||||
|
||||
[ViewVariables]
|
||||
private string _useSound;
|
||||
[ViewVariables]
|
||||
private string _trashPrototype;
|
||||
[ViewVariables]
|
||||
private SolutionComponent _contents;
|
||||
[ViewVariables]
|
||||
private ReagentUnit _transferAmount;
|
||||
[ViewVariables] private string _useSound = "";
|
||||
[ViewVariables] private string? _trashPrototype;
|
||||
[ViewVariables] private ReagentUnit _transferAmount;
|
||||
private UtensilType _utensilsNeeded;
|
||||
|
||||
public int UsesRemaining => _contents.CurrentVolume == 0
|
||||
?
|
||||
0 : Math.Max(1, (int)Math.Ceiling((_contents.CurrentVolume / _transferAmount).Float()));
|
||||
[ViewVariables]
|
||||
public int UsesRemaining
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return solution.CurrentVolume == 0
|
||||
? 0
|
||||
: Math.Max(1, (int)Math.Ceiling((solution.CurrentVolume / _transferAmount).Float()));
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
@@ -60,7 +67,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
||||
{
|
||||
var types = new List<UtensilType>();
|
||||
|
||||
foreach (UtensilType type in Enum.GetValues(typeof(UtensilType)))
|
||||
foreach (var type in (UtensilType[]) Enum.GetValues(typeof(UtensilType)))
|
||||
{
|
||||
if ((_utensilsNeeded & type) != 0)
|
||||
{
|
||||
@@ -75,8 +82,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_contents = Owner.GetComponent<SolutionComponent>();
|
||||
|
||||
Owner.EnsureComponent<SolutionComponent>();
|
||||
}
|
||||
|
||||
bool IUse.UseEntity(UseEntityEventArgs eventArgs)
|
||||
@@ -101,8 +107,13 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
||||
TryUseFood(eventArgs.User, eventArgs.Target);
|
||||
}
|
||||
|
||||
public virtual bool TryUseFood(IEntity user, IEntity target, UtensilComponent utensilUsed = null)
|
||||
public virtual bool TryUseFood(IEntity? user, IEntity? target, UtensilComponent? utensilUsed = null)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out SolutionComponent? solution))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return false;
|
||||
@@ -116,7 +127,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
||||
|
||||
var trueTarget = target ?? user;
|
||||
|
||||
if (!trueTarget.TryGetComponent(out StomachComponent stomach))
|
||||
if (!trueTarget.TryGetComponent(out StomachComponent? stomach))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -130,11 +141,11 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
||||
utensils = new List<UtensilComponent>();
|
||||
var types = UtensilType.None;
|
||||
|
||||
if (user.TryGetComponent(out HandsComponent hands))
|
||||
if (user.TryGetComponent(out HandsComponent? hands))
|
||||
{
|
||||
foreach (var item in hands.GetAllHeldItems())
|
||||
{
|
||||
if (!item.Owner.TryGetComponent(out UtensilComponent utensil))
|
||||
if (!item.Owner.TryGetComponent(out UtensilComponent? utensil))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -156,11 +167,11 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
||||
return false;
|
||||
}
|
||||
|
||||
var transferAmount = ReagentUnit.Min(_transferAmount, _contents.CurrentVolume);
|
||||
var split = _contents.SplitSolution(transferAmount);
|
||||
var transferAmount = ReagentUnit.Min(_transferAmount, solution.CurrentVolume);
|
||||
var split = solution.SplitSolution(transferAmount);
|
||||
if (!stomach.TryTransferSolution(split))
|
||||
{
|
||||
_contents.TryAddSolution(split);
|
||||
solution.TryAddSolution(split);
|
||||
trueTarget.PopupMessage(user, Loc.GetString("You can't eat any more!"));
|
||||
return false;
|
||||
}
|
||||
@@ -194,13 +205,13 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
||||
var finisher = Owner.EntityManager.SpawnEntity(_trashPrototype, position);
|
||||
|
||||
// If the user is holding the item
|
||||
if (user.TryGetComponent(out HandsComponent handsComponent) &&
|
||||
if (user.TryGetComponent(out HandsComponent? handsComponent) &&
|
||||
handsComponent.IsHolding(Owner))
|
||||
{
|
||||
Owner.Delete();
|
||||
|
||||
// Put the trash in the user's hand
|
||||
if (finisher.TryGetComponent(out ItemComponent item) &&
|
||||
if (finisher.TryGetComponent(out ItemComponent? item) &&
|
||||
handsComponent.CanPutInHand(item))
|
||||
{
|
||||
handsComponent.PutInHand(item);
|
||||
|
||||
@@ -37,21 +37,24 @@ namespace Content.Server.GameObjects.Components.PDA
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
[ViewVariables] private Container _idSlot = default!;
|
||||
[ViewVariables] private PointLightComponent _pdaLight = default!;
|
||||
[ViewVariables] private bool _lightOn;
|
||||
[ViewVariables] private BoundUserInterface _interface = default!;
|
||||
[ViewVariables] private string _startingIdCard = default!;
|
||||
[ViewVariables] public bool IdSlotEmpty => _idSlot.ContainedEntities.Count < 1;
|
||||
[ViewVariables] public string? OwnerName { get; private set; }
|
||||
|
||||
[ViewVariables] public IdCardComponent? ContainedID { get; private set; }
|
||||
|
||||
[ViewVariables] private AppearanceComponent _appearance = default!;
|
||||
|
||||
[ViewVariables] private UplinkAccount? _syndicateUplinkAccount;
|
||||
|
||||
[ViewVariables] private readonly PdaAccessSet _accessSet;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(PDAUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public PDAComponent()
|
||||
{
|
||||
_accessSet = new PdaAccessSet(this);
|
||||
@@ -67,11 +70,12 @@ namespace Content.Server.GameObjects.Components.PDA
|
||||
{
|
||||
base.Initialize();
|
||||
_idSlot = ContainerManagerComponent.Ensure<Container>("pda_entity_container", Owner, out var existed);
|
||||
_pdaLight = Owner.GetComponent<PointLightComponent>();
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
_interface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(PDAUiKey.Key);
|
||||
_interface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
}
|
||||
|
||||
var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.GridPosition);
|
||||
var idCardComponent = idCard.GetComponent<IdCardComponent>();
|
||||
_idSlot.Insert(idCardComponent.Owner);
|
||||
@@ -129,11 +133,11 @@ namespace Content.Server.GameObjects.Components.PDA
|
||||
var accData = new UplinkAccountData(_syndicateUplinkAccount.AccountHolder,
|
||||
_syndicateUplinkAccount.Balance);
|
||||
var listings = _uplinkManager.FetchListings.ToArray();
|
||||
_interface.SetState(new PDAUpdateState(_lightOn, ownerInfo, accData, listings));
|
||||
UserInterface?.SetState(new PDAUpdateState(_lightOn, ownerInfo, accData, listings));
|
||||
}
|
||||
else
|
||||
{
|
||||
_interface.SetState(new PDAUpdateState(_lightOn, ownerInfo));
|
||||
UserInterface?.SetState(new PDAUpdateState(_lightOn, ownerInfo));
|
||||
}
|
||||
|
||||
UpdatePDAAppearance();
|
||||
@@ -141,7 +145,10 @@ namespace Content.Server.GameObjects.Components.PDA
|
||||
|
||||
private void UpdatePDAAppearance()
|
||||
{
|
||||
_appearance?.SetData(PDAVisuals.FlashlightLit, _lightOn);
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(PDAVisuals.FlashlightLit, _lightOn);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
@@ -169,7 +176,7 @@ namespace Content.Server.GameObjects.Components.PDA
|
||||
return;
|
||||
}
|
||||
|
||||
_interface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
UpdatePDAAppearance();
|
||||
}
|
||||
|
||||
@@ -180,7 +187,7 @@ namespace Content.Server.GameObjects.Components.PDA
|
||||
return false;
|
||||
}
|
||||
|
||||
_interface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
UpdatePDAAppearance();
|
||||
return true;
|
||||
}
|
||||
@@ -217,8 +224,13 @@ namespace Content.Server.GameObjects.Components.PDA
|
||||
|
||||
private void ToggleLight()
|
||||
{
|
||||
if (!Owner.TryGetComponent(out PointLightComponent? light))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_lightOn = !_lightOn;
|
||||
_pdaLight.Enabled = _lightOn;
|
||||
light.Enabled = _lightOn;
|
||||
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Items/flashlight_toggle.ogg", Owner);
|
||||
UpdatePDAUserInterface();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -13,24 +14,30 @@ namespace Content.Server.GameObjects.Components.Paper
|
||||
[RegisterComponent]
|
||||
public class PaperComponent : SharedPaperComponent, IExamine, IInteractUsing, IUse
|
||||
{
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
private string _content;
|
||||
private string _content = "";
|
||||
private PaperAction _mode;
|
||||
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(PaperUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(PaperUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
_content = "";
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
_mode = PaperAction.Read;
|
||||
UpdateUserInterface();
|
||||
}
|
||||
private void UpdateUserInterface()
|
||||
{
|
||||
_userInterface.SetState(new PaperBoundUserInterfaceState(_content, _mode));
|
||||
UserInterface?.SetState(new PaperBoundUserInterfaceState(_content, _mode));
|
||||
}
|
||||
|
||||
public void Examine(FormattedMessage message, bool inDetailsRange)
|
||||
@@ -43,11 +50,12 @@ namespace Content.Server.GameObjects.Components.Paper
|
||||
|
||||
public bool UseEntity(UseEntityEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
return false;
|
||||
|
||||
_mode = PaperAction.Read;
|
||||
UpdateUserInterface();
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -59,7 +67,7 @@ namespace Content.Server.GameObjects.Components.Paper
|
||||
|
||||
_content += msg.Text + '\n';
|
||||
|
||||
if (Owner.TryGetComponent(out SpriteComponent sprite))
|
||||
if (Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||
{
|
||||
sprite.LayerSetState(1, "paper_words");
|
||||
}
|
||||
@@ -71,12 +79,12 @@ namespace Content.Server.GameObjects.Components.Paper
|
||||
{
|
||||
if (!eventArgs.Using.HasComponent<WriteComponent>())
|
||||
return false;
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
return false;
|
||||
|
||||
_mode = PaperAction.Write;
|
||||
UpdateUserInterface();
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
|
||||
using Content.Server.GameObjects.Components.Power.PowerNetComponents;
|
||||
using Content.Shared.GameObjects.Components.Power;
|
||||
@@ -20,17 +21,12 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class ApcComponent : BaseApcNetComponent, IActivate
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
public override string Name => "Apc";
|
||||
|
||||
[ViewVariables]
|
||||
public BatteryComponent Battery { get; private set; }
|
||||
|
||||
public bool MainBreakerEnabled { get; private set; } = true;
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
private AppearanceComponent _appearance;
|
||||
|
||||
private ApcChargeState _lastChargeState;
|
||||
|
||||
private TimeSpan _lastChargeStateChange;
|
||||
@@ -39,7 +35,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
|
||||
|
||||
private TimeSpan _lastExternalPowerStateChange;
|
||||
|
||||
private float _lastCharge = 0f;
|
||||
private float _lastCharge;
|
||||
|
||||
private TimeSpan _lastChargeChange;
|
||||
|
||||
@@ -49,17 +45,27 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
|
||||
|
||||
private const int VisualsChangeDelay = 1;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IGameTiming _gameTiming;
|
||||
#pragma warning restore 649
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(ApcUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public BatteryComponent? Battery => Owner.TryGetComponent(out BatteryComponent? batteryComponent) ? batteryComponent : null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
Battery = Owner.GetComponent<BatteryComponent>();
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(ApcUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
|
||||
Owner.EnsureComponent<BatteryComponent>();
|
||||
Owner.EnsureComponent<PowerConsumerComponent>();
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
}
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
@@ -90,15 +96,23 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
|
||||
{
|
||||
_lastChargeState = newState;
|
||||
_lastChargeStateChange = _gameTiming.CurTime;
|
||||
_appearance.SetData(ApcVisuals.ChargeState, newState);
|
||||
}
|
||||
var newCharge = Battery.CurrentCharge;
|
||||
if (newCharge != _lastCharge && _lastChargeChange + TimeSpan.FromSeconds(VisualsChangeDelay) < _gameTiming.CurTime)
|
||||
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
_lastCharge = newCharge;
|
||||
appearance.SetData(ApcVisuals.ChargeState, newState);
|
||||
}
|
||||
}
|
||||
|
||||
Owner.TryGetComponent(out BatteryComponent? battery);
|
||||
|
||||
var newCharge = battery?.CurrentCharge;
|
||||
if (newCharge != null && newCharge != _lastCharge && _lastChargeChange + TimeSpan.FromSeconds(VisualsChangeDelay) < _gameTiming.CurTime)
|
||||
{
|
||||
_lastCharge = newCharge.Value;
|
||||
_lastChargeChange = _gameTiming.CurTime;
|
||||
_uiDirty = true;
|
||||
}
|
||||
|
||||
var extPowerState = CalcExtPowerState();
|
||||
if (extPowerState != _lastExternalPowerState && _lastExternalPowerStateChange + TimeSpan.FromSeconds(VisualsChangeDelay) < _gameTiming.CurTime)
|
||||
{
|
||||
@@ -106,21 +120,33 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
|
||||
_lastExternalPowerStateChange = _gameTiming.CurTime;
|
||||
_uiDirty = true;
|
||||
}
|
||||
if (_uiDirty)
|
||||
|
||||
if (_uiDirty && battery != null && newCharge != null)
|
||||
{
|
||||
_userInterface.SetState(new ApcBoundInterfaceState(MainBreakerEnabled, extPowerState, newCharge / Battery.MaxCharge));
|
||||
UserInterface?.SetState(new ApcBoundInterfaceState(MainBreakerEnabled, extPowerState, newCharge.Value / battery.MaxCharge));
|
||||
_uiDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
private ApcChargeState CalcChargeState()
|
||||
{
|
||||
var chargeFraction = Battery.CurrentCharge / Battery.MaxCharge;
|
||||
if (!Owner.TryGetComponent(out BatteryComponent? battery))
|
||||
{
|
||||
return ApcChargeState.Lack;
|
||||
}
|
||||
|
||||
var chargeFraction = battery.CurrentCharge / battery.MaxCharge;
|
||||
|
||||
if (chargeFraction > HighPowerThreshold)
|
||||
{
|
||||
return ApcChargeState.Full;
|
||||
}
|
||||
var consumer = Owner.GetComponent<PowerConsumerComponent>();
|
||||
|
||||
if (!Owner.TryGetComponent(out PowerConsumerComponent? consumer))
|
||||
{
|
||||
return ApcChargeState.Full;
|
||||
}
|
||||
|
||||
if (consumer.DrawRate == consumer.ReceivedPower)
|
||||
{
|
||||
return ApcChargeState.Charging;
|
||||
@@ -133,7 +159,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
|
||||
|
||||
private ApcExternalPowerState CalcExtPowerState()
|
||||
{
|
||||
if (!Owner.TryGetComponent(out BatteryStorageComponent batteryStorage))
|
||||
if (!Owner.TryGetComponent(out BatteryStorageComponent? batteryStorage))
|
||||
{
|
||||
return ApcExternalPowerState.None;
|
||||
}
|
||||
@@ -154,11 +180,12 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_userInterface.Open(actor.playerSession);
|
||||
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
@@ -24,19 +25,14 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
public abstract class BaseCharger : Component, IActivate, IInteractUsing
|
||||
{
|
||||
[ViewVariables]
|
||||
private BatteryComponent _heldBattery;
|
||||
private BatteryComponent? _heldBattery;
|
||||
|
||||
[ViewVariables]
|
||||
private ContainerSlot _container;
|
||||
|
||||
[ViewVariables]
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private ContainerSlot _container = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private CellChargerStatus _status;
|
||||
|
||||
private AppearanceComponent _appearanceComponent;
|
||||
|
||||
[ViewVariables]
|
||||
private int _chargeRate;
|
||||
|
||||
@@ -53,16 +49,25 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
|
||||
Owner.EnsureComponent<PowerReceiverComponent>();
|
||||
_container = ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-powerCellContainer", Owner);
|
||||
_appearanceComponent = Owner.GetComponent<AppearanceComponent>();
|
||||
// Default state in the visualizer is OFF, so when this gets powered on during initialization it will generally show empty
|
||||
_powerReceiver.OnPowerStateChanged += PowerUpdate;
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged += PowerUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
_powerReceiver.OnPowerStateChanged -= PowerUpdate;
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged -= PowerUpdate;
|
||||
}
|
||||
|
||||
_heldBattery = null;
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
@@ -97,12 +102,12 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
|
||||
_container.Remove(heldItem);
|
||||
_heldBattery = null;
|
||||
if (user.TryGetComponent(out HandsComponent handsComponent))
|
||||
if (user.TryGetComponent(out HandsComponent? handsComponent))
|
||||
{
|
||||
handsComponent.PutInHandOrDrop(heldItem.GetComponent<ItemComponent>());
|
||||
}
|
||||
|
||||
if (heldItem.TryGetComponent(out ServerBatteryBarrelComponent batteryBarrelComponent))
|
||||
if (heldItem.TryGetComponent(out ServerBatteryBarrelComponent? batteryBarrelComponent))
|
||||
{
|
||||
batteryBarrelComponent.UpdateAppearance();
|
||||
}
|
||||
@@ -110,7 +115,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private void PowerUpdate(object sender, PowerStateEventArgs eventArgs)
|
||||
private void PowerUpdate(object? sender, PowerStateEventArgs eventArgs)
|
||||
{
|
||||
UpdateStatus();
|
||||
}
|
||||
@@ -125,7 +130,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
data.Visibility = VerbVisibility.Invisible;
|
||||
return;
|
||||
}
|
||||
if (!user.TryGetComponent(out HandsComponent handsComponent))
|
||||
if (!user.TryGetComponent(out HandsComponent? handsComponent))
|
||||
{
|
||||
data.Visibility = VerbVisibility.Invisible;
|
||||
return;
|
||||
@@ -143,7 +148,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
|
||||
protected override void Activate(IEntity user, BaseCharger component)
|
||||
{
|
||||
if (!user.TryGetComponent(out HandsComponent handsComponent))
|
||||
if (!user.TryGetComponent(out HandsComponent? handsComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -186,7 +191,8 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
|
||||
private CellChargerStatus GetStatus()
|
||||
{
|
||||
if (!_powerReceiver.Powered)
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver) &&
|
||||
!receiver.Powered)
|
||||
{
|
||||
return CellChargerStatus.Off;
|
||||
}
|
||||
@@ -227,34 +233,39 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
{
|
||||
// Not called UpdateAppearance just because it messes with the load
|
||||
var status = GetStatus();
|
||||
if (_status == status)
|
||||
if (_status == status ||
|
||||
!Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_status = status;
|
||||
Owner.TryGetComponent(out AppearanceComponent? appearance);
|
||||
|
||||
switch (_status)
|
||||
{
|
||||
// Update load just in case
|
||||
case CellChargerStatus.Off:
|
||||
_powerReceiver.Load = 0;
|
||||
_appearanceComponent?.SetData(CellVisual.Light, CellChargerStatus.Off);
|
||||
receiver.Load = 0;
|
||||
appearance?.SetData(CellVisual.Light, CellChargerStatus.Off);
|
||||
break;
|
||||
case CellChargerStatus.Empty:
|
||||
_powerReceiver.Load = 0;
|
||||
_appearanceComponent?.SetData(CellVisual.Light, CellChargerStatus.Empty); ;
|
||||
receiver.Load = 0;
|
||||
appearance?.SetData(CellVisual.Light, CellChargerStatus.Empty);
|
||||
break;
|
||||
case CellChargerStatus.Charging:
|
||||
_powerReceiver.Load = (int) (_chargeRate / _transferEfficiency);
|
||||
_appearanceComponent?.SetData(CellVisual.Light, CellChargerStatus.Charging);
|
||||
receiver.Load = (int) (_chargeRate / _transferEfficiency);
|
||||
appearance?.SetData(CellVisual.Light, CellChargerStatus.Charging);
|
||||
break;
|
||||
case CellChargerStatus.Charged:
|
||||
_powerReceiver.Load = 0;
|
||||
_appearanceComponent?.SetData(CellVisual.Light, CellChargerStatus.Charged);
|
||||
receiver.Load = 0;
|
||||
appearance?.SetData(CellVisual.Light, CellChargerStatus.Charged);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
_appearanceComponent?.SetData(CellVisual.Occupied, _container.ContainedEntity != null);
|
||||
|
||||
appearance?.SetData(CellVisual.Occupied, _container.ContainedEntity != null);
|
||||
}
|
||||
|
||||
public void OnUpdate(float frameTime) //todo: make single system for this
|
||||
@@ -268,10 +279,17 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
|
||||
private void TransferPower(float frameTime)
|
||||
{
|
||||
if (!_powerReceiver.Powered)
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver) &&
|
||||
!receiver.Powered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_heldBattery == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_heldBattery.CurrentCharge += _chargeRate * frameTime;
|
||||
// Just so the sprite won't be set to 99.99999% visibility
|
||||
if (_heldBattery.MaxCharge - _heldBattery.CurrentCharge < 0.01)
|
||||
|
||||
@@ -108,7 +108,11 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
|
||||
public void UpdateColor()
|
||||
{
|
||||
var sprite = Owner.GetComponent<SpriteComponent>();
|
||||
if (!Owner.TryGetComponent(out SpriteComponent sprite))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sprite.Color = Color;
|
||||
}
|
||||
|
||||
|
||||
@@ -225,14 +225,18 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
Owner.GetComponent<PowerReceiverComponent>().OnPowerStateChanged += UpdateLight;
|
||||
Owner.EnsureComponent<PowerReceiverComponent>().OnPowerStateChanged += UpdateLight;
|
||||
|
||||
_lightBulbContainer = ContainerManagerComponent.Ensure<ContainerSlot>("light_bulb", Owner);
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
Owner.GetComponent<PowerReceiverComponent>().OnPowerStateChanged -= UpdateLight;
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged -= UpdateLight;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,9 @@ namespace Content.Server.GameObjects.Components.Power
|
||||
{
|
||||
public override string Name => "PowerCell";
|
||||
|
||||
private AppearanceComponent _appearance;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
CurrentCharge = MaxCharge;
|
||||
UpdateVisuals();
|
||||
}
|
||||
@@ -31,7 +28,10 @@ namespace Content.Server.GameObjects.Components.Power
|
||||
|
||||
private void UpdateVisuals()
|
||||
{
|
||||
_appearance?.SetData(PowerCellVisuals.ChargeLevel, CurrentCharge / MaxCharge);
|
||||
if (Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||
{
|
||||
appearance.SetData(PowerCellVisuals.ChargeLevel, CurrentCharge / MaxCharge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,9 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_battery = Owner.GetComponent<BatteryComponent>();
|
||||
_supplier = Owner.GetComponent<PowerSupplierComponent>();
|
||||
|
||||
_battery = Owner.EnsureComponent<BatteryComponent>();
|
||||
_supplier = Owner.EnsureComponent<PowerSupplierComponent>();
|
||||
UpdateSupplyRate();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,9 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_battery = Owner.GetComponent<BatteryComponent>();
|
||||
Consumer = Owner.GetComponent<PowerConsumerComponent>();
|
||||
|
||||
_battery = Owner.EnsureComponent<BatteryComponent>();
|
||||
Consumer = Owner.EnsureComponent<PowerConsumerComponent>();
|
||||
UpdateDrawRate();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using Content.Shared.GameObjects.Components.Power;
|
||||
using Content.Shared.Utility;
|
||||
using Robust.Server.GameObjects;
|
||||
@@ -16,13 +17,11 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
[RegisterComponent]
|
||||
public class SmesComponent : Component
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
public override string Name => "Smes";
|
||||
|
||||
private BatteryComponent _battery;
|
||||
|
||||
private AppearanceComponent _appearance;
|
||||
|
||||
private int _lastChargeLevel = 0;
|
||||
private int _lastChargeLevel;
|
||||
|
||||
private TimeSpan _lastChargeLevelChange;
|
||||
|
||||
@@ -32,15 +31,12 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
|
||||
private const int VisualsChangeDelay = 1;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IGameTiming _gameTiming;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_battery = Owner.GetComponent<BatteryComponent>();
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
|
||||
Owner.EnsureComponent<BatteryComponent>();
|
||||
Owner.EnsureComponent<AppearanceComponent>();
|
||||
}
|
||||
|
||||
public void OnUpdate()
|
||||
@@ -50,7 +46,11 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
{
|
||||
_lastChargeLevel = newLevel;
|
||||
_lastChargeLevelChange = _gameTiming.CurTime;
|
||||
_appearance.SetData(SmesVisuals.LastChargeLevel, newLevel);
|
||||
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(SmesVisuals.LastChargeLevel, newLevel);
|
||||
}
|
||||
}
|
||||
|
||||
var newChargeState = GetNewChargeState();
|
||||
@@ -58,13 +58,22 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
{
|
||||
_lastChargeState = newChargeState;
|
||||
_lastChargeStateChange = _gameTiming.CurTime;
|
||||
_appearance.SetData(SmesVisuals.LastChargeState, newChargeState);
|
||||
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(SmesVisuals.LastChargeState, newChargeState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int GetNewChargeLevel()
|
||||
{
|
||||
return ContentHelpers.RoundToLevels(_battery.CurrentCharge, _battery.MaxCharge, 6);
|
||||
if (!Owner.TryGetComponent(out BatteryComponent? battery))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ContentHelpers.RoundToLevels(battery.CurrentCharge, battery.MaxCharge, 6);
|
||||
}
|
||||
|
||||
private ChargeState GetNewChargeState()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Components.Power;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -7,6 +8,7 @@ using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
{
|
||||
@@ -14,28 +16,34 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class SolarControlConsoleComponent : SharedSolarControlConsoleComponent, IActivate
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IEntitySystemManager _entitySystemManager;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private PowerSolarSystem _powerSolarSystem;
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
private PowerSolarSystem _powerSolarSystem = default!;
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(SolarControlConsoleUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(SolarControlConsoleUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
}
|
||||
|
||||
Owner.EnsureComponent<PowerReceiverComponent>();
|
||||
_powerSolarSystem = _entitySystemManager.GetEntitySystem<PowerSolarSystem>();
|
||||
}
|
||||
|
||||
public void UpdateUIState()
|
||||
{
|
||||
_userInterface.SetState(new SolarControlConsoleBoundInterfaceState(_powerSolarSystem.TargetPanelRotation, _powerSolarSystem.TargetPanelVelocity, _powerSolarSystem.TotalPanelPower, _powerSolarSystem.TowardsSun));
|
||||
UserInterface?.SetState(new SolarControlConsoleBoundInterfaceState(_powerSolarSystem.TargetPanelRotation, _powerSolarSystem.TargetPanelVelocity, _powerSolarSystem.TotalPanelPower, _powerSolarSystem.TowardsSun));
|
||||
}
|
||||
|
||||
private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
@@ -57,7 +65,7 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -69,7 +77,7 @@ namespace Content.Server.GameObjects.Components.Power.PowerNetComponents
|
||||
|
||||
// always update the UI immediately before opening, just in case
|
||||
UpdateUIState();
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,16 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
if (!Owner.HasComponent<ExplosiveComponent>())
|
||||
{
|
||||
Logger.Error("ExplosiveProjectiles need an ExplosiveComponent");
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
Owner.EnsureComponent<ExplosiveComponent>();
|
||||
}
|
||||
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
{
|
||||
var explosiveComponent = Owner.GetComponent<ExplosiveComponent>();
|
||||
explosiveComponent.Explosion();
|
||||
if (Owner.TryGetComponent(out ExplosiveComponent explosive))
|
||||
{
|
||||
explosive.Explosion();
|
||||
}
|
||||
}
|
||||
|
||||
// Projectile should handle the deleting
|
||||
|
||||
@@ -31,10 +31,7 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
{
|
||||
base.Initialize();
|
||||
// Shouldn't be using this without a ProjectileComponent because it will just immediately collide with thrower
|
||||
if (!Owner.HasComponent<ProjectileComponent>())
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
Owner.EnsureComponent<ProjectileComponent>();
|
||||
}
|
||||
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
|
||||
@@ -12,10 +12,8 @@ namespace Content.Server.GameObjects.Components
|
||||
[RegisterComponent]
|
||||
class RadioComponent : Component, IUse, IListen
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "Radio";
|
||||
|
||||
|
||||
@@ -28,9 +28,7 @@ namespace Content.Server.GameObjects.Components.Recycling
|
||||
[RegisterComponent]
|
||||
public class RecyclerComponent : Component, ICollideBehavior
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "Recycler";
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -25,15 +26,12 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
{
|
||||
public const int VolumePerSheet = 3750;
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
[ViewVariables]
|
||||
public Queue<LatheRecipePrototype> Queue { get; } = new Queue<LatheRecipePrototype>();
|
||||
|
||||
[ViewVariables]
|
||||
public bool Producing { get; private set; } = false;
|
||||
public bool Producing { get; private set; }
|
||||
|
||||
private AppearanceComponent _appearance;
|
||||
private LatheState _state = LatheState.Base;
|
||||
|
||||
protected virtual LatheState State
|
||||
@@ -42,19 +40,26 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
set => _state = value;
|
||||
}
|
||||
|
||||
private LatheRecipePrototype _producingRecipe = null;
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
private LatheRecipePrototype? _producingRecipe;
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
private static readonly TimeSpan InsertionTime = TimeSpan.FromSeconds(0.9f);
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(LatheUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(LatheUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message)
|
||||
@@ -66,28 +71,28 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
{
|
||||
case LatheQueueRecipeMessage msg:
|
||||
_prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype recipe);
|
||||
if (recipe != null)
|
||||
if (recipe != null!)
|
||||
for (var i = 0; i < msg.Quantity; i++)
|
||||
{
|
||||
Queue.Enqueue(recipe);
|
||||
_userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue()));
|
||||
UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue()));
|
||||
}
|
||||
break;
|
||||
case LatheSyncRequestMessage msg:
|
||||
if (!Owner.TryGetComponent(out MaterialStorageComponent storage)) return;
|
||||
_userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue()));
|
||||
case LatheSyncRequestMessage _:
|
||||
if (!Owner.HasComponent<MaterialStorageComponent>()) return;
|
||||
UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue()));
|
||||
if (_producingRecipe != null)
|
||||
_userInterface.SendMessage(new LatheProducingRecipeMessage(_producingRecipe.ID));
|
||||
UserInterface?.SendMessage(new LatheProducingRecipeMessage(_producingRecipe.ID));
|
||||
break;
|
||||
|
||||
case LatheServerSelectionMessage msg:
|
||||
if (!Owner.TryGetComponent(out ResearchClientComponent researchClient)) return;
|
||||
case LatheServerSelectionMessage _:
|
||||
if (!Owner.TryGetComponent(out ResearchClientComponent? researchClient)) return;
|
||||
researchClient.OpenUserInterface(message.Session);
|
||||
break;
|
||||
|
||||
case LatheServerSyncMessage msg:
|
||||
if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database)
|
||||
|| !Owner.TryGetComponent(out ProtolatheDatabaseComponent protoDatabase)) return;
|
||||
case LatheServerSyncMessage _:
|
||||
if (!Owner.TryGetComponent(out TechnologyDatabaseComponent? database)
|
||||
|| !Owner.TryGetComponent(out ProtolatheDatabaseComponent? protoDatabase)) return;
|
||||
|
||||
if (database.SyncWithServer())
|
||||
protoDatabase.Sync();
|
||||
@@ -103,9 +108,9 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Producing || !CanProduce(recipe) || !Owner.TryGetComponent(out MaterialStorageComponent storage)) return false;
|
||||
if (Producing || !CanProduce(recipe) || !Owner.TryGetComponent(out MaterialStorageComponent? storage)) return false;
|
||||
|
||||
_userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue()));
|
||||
UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue()));
|
||||
|
||||
Producing = true;
|
||||
_producingRecipe = recipe;
|
||||
@@ -116,7 +121,7 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
storage.RemoveMaterial(material, amount);
|
||||
}
|
||||
|
||||
_userInterface.SendMessage(new LatheProducingRecipeMessage(recipe.ID));
|
||||
UserInterface?.SendMessage(new LatheProducingRecipeMessage(recipe.ID));
|
||||
|
||||
State = LatheState.Producing;
|
||||
SetAppearance(LatheVisualState.Producing);
|
||||
@@ -126,7 +131,7 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
Producing = false;
|
||||
_producingRecipe = null;
|
||||
Owner.EntityManager.SpawnEntity(recipe.Result, Owner.Transform.GridPosition);
|
||||
_userInterface.SendMessage(new LatheStoppedProducingRecipeMessage());
|
||||
UserInterface?.SendMessage(new LatheStoppedProducingRecipeMessage());
|
||||
State = LatheState.Base;
|
||||
SetAppearance(LatheVisualState.Idle);
|
||||
});
|
||||
@@ -136,12 +141,12 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
|
||||
public void OpenUserInterface(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
return;
|
||||
if (!Powered)
|
||||
{
|
||||
@@ -153,12 +158,12 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
|
||||
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out MaterialStorageComponent storage)
|
||||
|| !eventArgs.Using.TryGetComponent(out MaterialComponent material)) return false;
|
||||
if (!Owner.TryGetComponent(out MaterialStorageComponent? storage)
|
||||
|| !eventArgs.Using.TryGetComponent(out MaterialComponent? material)) return false;
|
||||
|
||||
var multiplier = 1;
|
||||
|
||||
if (eventArgs.Using.TryGetComponent(out StackComponent stack)) multiplier = stack.Count;
|
||||
if (eventArgs.Using.TryGetComponent(out StackComponent? stack)) multiplier = stack.Count;
|
||||
|
||||
var totalAmount = 0;
|
||||
|
||||
@@ -205,11 +210,13 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
|
||||
private void SetAppearance(LatheVisualState state)
|
||||
{
|
||||
if (_appearance != null || Owner.TryGetComponent(out _appearance))
|
||||
_appearance.SetData(PowerDeviceVisuals.VisualState, state);
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(PowerDeviceVisuals.VisualState, state);
|
||||
}
|
||||
}
|
||||
|
||||
private Queue<string> GetIDQueue()
|
||||
private Queue<string> GetIdQueue()
|
||||
{
|
||||
var queue = new Queue<string>();
|
||||
foreach (var recipePrototype in Queue)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Components.Research;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Server.GameObjects.Components.UserInterface;
|
||||
@@ -14,20 +15,21 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
[RegisterComponent]
|
||||
public class ResearchClientComponent : SharedResearchClientComponent, IActivate
|
||||
{
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
|
||||
// TODO: Create GUI for changing RD server.
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
||||
#pragma warning restore 649
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(ResearchClientUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public bool ConnectedToServer => Server != null;
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public ResearchServerComponent Server { get; set; }
|
||||
public ResearchServerComponent? Server { get; set; }
|
||||
|
||||
public bool RegisterServer(ResearchServerComponent server)
|
||||
public bool RegisterServer(ResearchServerComponent? server)
|
||||
{
|
||||
var result = server != null && server.RegisterClient(this);
|
||||
return result;
|
||||
@@ -41,23 +43,28 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
// For now it just registers on the first server it can find.
|
||||
var servers = _entitySystemManager.GetEntitySystem<ResearchSystem>().Servers;
|
||||
if(servers.Count > 0)
|
||||
|
||||
if (servers.Count > 0)
|
||||
RegisterServer(servers[0]);
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(ResearchClientUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenUserInterface(IPlayerSession session)
|
||||
{
|
||||
UpdateUserInterface();
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
return;
|
||||
|
||||
OpenUserInterface(actor.playerSession);
|
||||
@@ -65,7 +72,7 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
|
||||
public void UpdateUserInterface()
|
||||
{
|
||||
_userInterface?.SetState(GetNewUiState());
|
||||
UserInterface?.SetState(GetNewUiState());
|
||||
}
|
||||
|
||||
private ResearchClientBoundInterfaceState GetNewUiState()
|
||||
@@ -73,7 +80,7 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
var rd = _entitySystemManager.GetEntitySystem<ResearchSystem>();
|
||||
|
||||
return new ResearchClientBoundInterfaceState(rd.Servers.Count, rd.GetServerNames(),
|
||||
rd.GetServerIds(), ConnectedToServer ? Server.Id : -1);
|
||||
rd.GetServerIds(), ConnectedToServer ? Server!.Id : -1);
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage msg)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.GameObjects.Components.Research;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -14,6 +15,7 @@ using Robust.Shared.Interfaces.Random;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Research
|
||||
{
|
||||
@@ -21,31 +23,38 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class ResearchConsoleComponent : SharedResearchConsoleComponent, IActivate
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||
[Dependency] private readonly IRobustRandom _random;
|
||||
#pragma warning restore 649
|
||||
private const string SoundCollectionName = "keyboard";
|
||||
|
||||
private BoundUserInterface _userInterface;
|
||||
private ResearchClientComponent _client;
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
private const string _soundCollectionName = "keyboard";
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
[ViewVariables]
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(ResearchConsoleUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(ResearchConsoleUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
_client = Owner.GetComponent<ResearchClientComponent>();
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
|
||||
Owner.EnsureComponent<ResearchClientComponent>();
|
||||
}
|
||||
|
||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database)) return;
|
||||
if (!Owner.TryGetComponent(out TechnologyDatabaseComponent? database))
|
||||
return;
|
||||
if (!Owner.TryGetComponent(out ResearchClientComponent? client))
|
||||
return;
|
||||
if (!Powered)
|
||||
return;
|
||||
|
||||
@@ -54,8 +63,9 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
case ConsoleUnlockTechnologyMessage msg:
|
||||
var protoMan = IoCManager.Resolve<IPrototypeManager>();
|
||||
if (!protoMan.TryIndex(msg.Id, out TechnologyPrototype tech)) break;
|
||||
if(!_client.Server.CanUnlockTechnology(tech)) break;
|
||||
if (_client.Server.UnlockTechnology(tech))
|
||||
if (client.Server == null) break;
|
||||
if (!client.Server.CanUnlockTechnology(tech)) break;
|
||||
if (client.Server.UnlockTechnology(tech))
|
||||
{
|
||||
database.SyncWithServer();
|
||||
database.Dirty();
|
||||
@@ -64,13 +74,12 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
|
||||
break;
|
||||
|
||||
case ConsoleServerSyncMessage msg:
|
||||
case ConsoleServerSyncMessage _:
|
||||
database.SyncWithServer();
|
||||
UpdateUserInterface();
|
||||
break;
|
||||
|
||||
case ConsoleServerSelectionMessage msg:
|
||||
if (!Owner.TryGetComponent(out ResearchClientComponent client)) break;
|
||||
case ConsoleServerSelectionMessage _:
|
||||
client.OpenUserInterface(message.Session);
|
||||
break;
|
||||
}
|
||||
@@ -81,13 +90,17 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
/// </summary>
|
||||
public void UpdateUserInterface()
|
||||
{
|
||||
_userInterface.SetState(GetNewUiState());
|
||||
UserInterface?.SetState(GetNewUiState());
|
||||
}
|
||||
|
||||
private ResearchConsoleBoundInterfaceState GetNewUiState()
|
||||
{
|
||||
var points = _client.ConnectedToServer ? _client.Server.Point : 0;
|
||||
var pointsPerSecond = _client.ConnectedToServer ? _client.Server.PointsPerSecond : 0;
|
||||
if (!Owner.TryGetComponent(out ResearchClientComponent? client) ||
|
||||
client.Server == null)
|
||||
return new ResearchConsoleBoundInterfaceState(default, default);
|
||||
|
||||
var points = client.ConnectedToServer ? client.Server.Point : 0;
|
||||
var pointsPerSecond = client.ConnectedToServer ? client.Server.PointsPerSecond : 0;
|
||||
|
||||
return new ResearchConsoleBoundInterfaceState(points, pointsPerSecond);
|
||||
}
|
||||
@@ -98,12 +111,12 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
/// <param name="session">Session where the UI will be shown</param>
|
||||
public void OpenUserInterface(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
return;
|
||||
if (!Powered)
|
||||
{
|
||||
@@ -112,17 +125,14 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
|
||||
OpenUserInterface(actor.playerSession);
|
||||
PlayKeyboardSound();
|
||||
return;
|
||||
}
|
||||
|
||||
private void PlayKeyboardSound()
|
||||
{
|
||||
var soundCollection = _prototypeManager.Index<SoundCollectionPrototype>(_soundCollectionName);
|
||||
var soundCollection = _prototypeManager.Index<SoundCollectionPrototype>(SoundCollectionName);
|
||||
var file = _random.Pick(soundCollection.PickFiles);
|
||||
var audioSystem = EntitySystem.Get<AudioSystem>();
|
||||
audioSystem.PlayFromEntity(file,Owner,AudioParams.Default);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Content.Server.GameObjects.Components.Research
|
||||
base.Initialize();
|
||||
Id = ServerCount++;
|
||||
EntitySystem.Get<ResearchSystem>()?.RegisterServer(this);
|
||||
Database = Owner.GetComponent<TechnologyDatabaseComponent>();
|
||||
Database = Owner.EnsureComponent<TechnologyDatabaseComponent>();
|
||||
Owner.TryGetComponent(out _powerReceiver);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@ namespace Content.Server.GameObjects.Components.Rotatable
|
||||
[RegisterComponent]
|
||||
public class FlippableComponent : Component
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "Flippable";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Components.VendingMachines;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
@@ -29,27 +29,28 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class VendingMachineComponent : SharedVendingMachineComponent, IActivate, IExamine, IBreakAct, IWires
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IRobustRandom _random;
|
||||
#pragma warning restore 649
|
||||
private AppearanceComponent _appearance;
|
||||
private BoundUserInterface _userInterface;
|
||||
private PowerReceiverComponent _powerReceiver;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
private bool _ejecting = false;
|
||||
private bool _ejecting;
|
||||
private TimeSpan _animationDuration = TimeSpan.Zero;
|
||||
private string _packPrototypeId;
|
||||
private string _description;
|
||||
private string _spriteName;
|
||||
private string _packPrototypeId = "";
|
||||
private string? _description;
|
||||
private string _spriteName = "";
|
||||
|
||||
private bool Powered => _powerReceiver.Powered;
|
||||
private bool _broken = false;
|
||||
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||
private bool _broken;
|
||||
|
||||
private string _soundVend;
|
||||
private string _soundVend = "";
|
||||
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(VendingMachineUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public void Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if(!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
if(!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -62,7 +63,7 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
||||
wires.OpenInterface(actor.playerSession);
|
||||
} else
|
||||
{
|
||||
_userInterface.Open(actor.playerSession);
|
||||
UserInterface?.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,25 +107,32 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(VendingMachineUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||
_powerReceiver.OnPowerStateChanged += UpdatePower;
|
||||
TrySetVisualState(_powerReceiver.Powered ? VendingMachineVisualState.Normal : VendingMachineVisualState.Off);
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged += UpdatePower;
|
||||
TrySetVisualState(receiver.Powered ? VendingMachineVisualState.Normal : VendingMachineVisualState.Off);
|
||||
}
|
||||
|
||||
InitializeFromPrototype();
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
_appearance = null;
|
||||
_powerReceiver.OnPowerStateChanged -= UpdatePower;
|
||||
_powerReceiver = null;
|
||||
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
|
||||
{
|
||||
receiver.OnPowerStateChanged -= UpdatePower;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
private void UpdatePower(object sender, PowerStateEventArgs args)
|
||||
private void UpdatePower(object? sender, PowerStateEventArgs args)
|
||||
{
|
||||
var state = args.Powered ? VendingMachineVisualState.Normal : VendingMachineVisualState.Off;
|
||||
TrySetVisualState(state);
|
||||
@@ -141,8 +149,8 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
||||
case VendingMachineEjectMessage msg:
|
||||
TryEject(msg.ID);
|
||||
break;
|
||||
case InventorySyncRequestMessage msg:
|
||||
_userInterface.SendMessage(new VendingMachineInventoryMessage(Inventory));
|
||||
case InventorySyncRequestMessage _:
|
||||
UserInterface?.SendMessage(new VendingMachineInventoryMessage(Inventory));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +168,7 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
||||
return;
|
||||
}
|
||||
|
||||
VendingMachineInventoryEntry entry = Inventory.Find(x => x.ID == id);
|
||||
var entry = Inventory.Find(x => x.ID == id);
|
||||
if (entry == null)
|
||||
{
|
||||
FlickDenyAnimation();
|
||||
@@ -175,7 +183,7 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
||||
|
||||
_ejecting = true;
|
||||
entry.Amount--;
|
||||
_userInterface.SendMessage(new VendingMachineInventoryMessage(Inventory));
|
||||
UserInterface?.SendMessage(new VendingMachineInventoryMessage(Inventory));
|
||||
TrySetVisualState(VendingMachineVisualState.Eject);
|
||||
|
||||
Timer.Spawn(_animationDuration, () =>
|
||||
@@ -204,14 +212,20 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
||||
if (_broken)
|
||||
{
|
||||
finalState = VendingMachineVisualState.Broken;
|
||||
} else if (_ejecting)
|
||||
}
|
||||
else if (_ejecting)
|
||||
{
|
||||
finalState = VendingMachineVisualState.Eject;
|
||||
} else if (!Powered)
|
||||
}
|
||||
else if (!Powered)
|
||||
{
|
||||
finalState = VendingMachineVisualState.Off;
|
||||
}
|
||||
_appearance.SetData(VendingMachineVisuals.VisualState, finalState);
|
||||
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(VendingMachineVisuals.VisualState, finalState);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBreak(BreakageEventArgs eventArgs)
|
||||
|
||||
@@ -158,7 +158,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
{
|
||||
base.OnAdd();
|
||||
var rangedWeaponComponent = Owner.GetComponent<ServerRangedWeaponComponent>();
|
||||
rangedWeaponComponent.Barrel = this;
|
||||
|
||||
rangedWeaponComponent.Barrel ??= this;
|
||||
rangedWeaponComponent.FireHandler += Fire;
|
||||
rangedWeaponComponent.WeaponCanFireHandler += WeaponCanFire;
|
||||
}
|
||||
|
||||
@@ -33,13 +33,11 @@ namespace Content.Server.GameObjects.Components
|
||||
[RegisterComponent]
|
||||
public class WiresComponent : SharedWiresComponent, IInteractUsing, IExamine, IMapInit
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
private AudioSystem _audioSystem = default!;
|
||||
private AppearanceComponent _appearance = default!;
|
||||
private BoundUserInterface _userInterface = default!;
|
||||
|
||||
private bool _isPanelOpen;
|
||||
|
||||
@@ -140,15 +138,23 @@ namespace Content.Server.GameObjects.Components
|
||||
[ViewVariables]
|
||||
private string? _layoutId;
|
||||
|
||||
private BoundUserInterface? UserInterface =>
|
||||
Owner.TryGetComponent(out ServerUserInterfaceComponent? ui) &&
|
||||
ui.TryGetBoundUserInterface(WiresUiKey.Key, out var boundUi)
|
||||
? boundUi
|
||||
: null;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_audioSystem = EntitySystem.Get<AudioSystem>();
|
||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||
_appearance.SetData(WiresVisuals.MaintenancePanelState, IsPanelOpen);
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(WiresUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateSerialNumber()
|
||||
@@ -357,7 +363,7 @@ namespace Content.Server.GameObjects.Components
|
||||
/// </summary>
|
||||
public void OpenInterface(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
}
|
||||
|
||||
private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage serverMsg)
|
||||
@@ -450,7 +456,7 @@ namespace Content.Server.GameObjects.Components
|
||||
entry.Letter));
|
||||
}
|
||||
|
||||
_userInterface.SetState(
|
||||
UserInterface?.SetState(
|
||||
new WiresBoundUserInterfaceState(
|
||||
clientList.ToArray(),
|
||||
_statuses.Select(p => new StatusEntry(p.Key, p.Value)).ToArray(),
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI
|
||||
/// <param name="controller"></param>
|
||||
public void ProcessorInitialize(AiControllerComponent controller)
|
||||
{
|
||||
if (controller.Processor != null) return;
|
||||
if (controller.Processor != null || controller.LogicName == null) return;
|
||||
controller.Processor = CreateProcessor(controller.LogicName);
|
||||
controller.Processor.SelfEntity = controller.Owner;
|
||||
controller.Processor.Setup();
|
||||
|
||||
@@ -153,13 +153,20 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
|
||||
private bool TryRefreshTile(GridAtmosphereComponent gam, GasOverlayData oldTile, MapIndices indices, out GasOverlayData overlayData)
|
||||
{
|
||||
var tile = gam.GetTile(indices);
|
||||
|
||||
if (tile == null)
|
||||
{
|
||||
overlayData = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
var tileData = new List<GasData>();
|
||||
|
||||
for (byte i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
{
|
||||
var gas = Atmospherics.GetGas(i);
|
||||
var overlay = Atmospherics.GetOverlay(i);
|
||||
if (overlay == null || tile.Air == null) continue;
|
||||
if (overlay == null || tile?.Air == null) continue;
|
||||
|
||||
var moles = tile.Air.Gases[i];
|
||||
|
||||
@@ -169,7 +176,7 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
|
||||
tileData.Add(data);
|
||||
}
|
||||
|
||||
overlayData = new GasOverlayData(tile.Hotspot.State, tile.Hotspot.Temperature, tileData.Count == 0 ? null : tileData.ToArray());
|
||||
overlayData = new GasOverlayData(tile!.Hotspot.State, tile.Hotspot.Temperature, tileData.Count == 0 ? null : tileData.ToArray());
|
||||
|
||||
if (overlayData.Equals(oldTile))
|
||||
{
|
||||
|
||||
@@ -30,13 +30,11 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
[UsedImplicitly]
|
||||
internal class MoverSystem : SharedMoverSystem
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPauseManager _pauseManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
private AudioSystem _audioSystem = default!;
|
||||
|
||||
|
||||
@@ -21,9 +21,7 @@ namespace Content.Shared.GameObjects.Components.Damage
|
||||
[ComponentReference(typeof(IDamageableComponent))]
|
||||
public class DamageableComponent : Component, IDamageableComponent
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override string Name => "Damageable";
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Physics;
|
||||
@@ -7,6 +8,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -116,12 +118,18 @@ namespace Content.Shared.GameObjects.Components.Movement
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
var collidable = Owner.GetComponent<ICollidableComponent>();
|
||||
|
||||
var collidable = Owner.EnsureComponent<CollidableComponent>();
|
||||
|
||||
collidable.Hard = false;
|
||||
var shape = collidable.PhysicsShapes[0];
|
||||
|
||||
var shape = collidable.PhysicsShapes.FirstOrDefault();
|
||||
|
||||
if (shape != null)
|
||||
{
|
||||
shape.CollisionLayer |= (int) CollisionGroup.SmallImpassable;
|
||||
shape.CollisionMask = (int)CollisionGroup.None;
|
||||
shape.CollisionMask = (int) CollisionGroup.None;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
<s:String x:Key="/Default/FilterSettingsManager/CoverageFilterXml/@EntryValue"><data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="Lidgren.Network" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /></ExcludeFilters></data></s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Collidable/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Cooldowns/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Discharger/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=crit/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=firelocks/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=diminishingly/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
Reference in New Issue
Block a user