Component ECS (#17991)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Player;
|
||||
@@ -34,7 +35,7 @@ public sealed class ClientAlertsSystem : AlertsSystem
|
||||
|
||||
AlertOrder = _prototypeManager.EnumeratePrototypes<AlertOrderPrototype>().FirstOrDefault();
|
||||
if (AlertOrder == null)
|
||||
Logger.ErrorS("alert", "no alertOrder prototype found, alerts will be in random order");
|
||||
Log.Error("alert", "no alertOrder prototype found, alerts will be in random order");
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<AlertKey, AlertState>? ActiveAlerts
|
||||
@@ -67,9 +68,10 @@ public sealed class ClientAlertsSystem : AlertsSystem
|
||||
private void ClientAlertsHandleState(EntityUid uid, AlertsComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
var componentAlerts = (args.Current as AlertsComponentState)?.Alerts;
|
||||
if (componentAlerts == null) return;
|
||||
if (componentAlerts == null)
|
||||
return;
|
||||
|
||||
component.Alerts = new(componentAlerts);
|
||||
component.Alerts = new Dictionary<AlertKey, AlertState>(componentAlerts);
|
||||
|
||||
if (_playerManager.LocalPlayer?.ControlledEntity == uid)
|
||||
SyncAlerts?.Invoke(this, componentAlerts);
|
||||
|
||||
@@ -31,10 +31,9 @@ namespace Content.Client.Atmos.EntitySystems
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
_overlayMan.RemoveOverlay<GasTileOverlay>();
|
||||
}
|
||||
|
||||
|
||||
private void OnHandleState(EntityUid gridUid, GasTileOverlayComponent comp, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not GasTileOverlayState state)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Alerts;
|
||||
using Content.Client.Humanoid;
|
||||
using Content.Client.Inventory;
|
||||
using Content.Client.Preferences;
|
||||
|
||||
@@ -396,21 +396,11 @@ namespace Content.IntegrationTests.Tests.Networking
|
||||
public sealed class PredictionTestComponent : Component
|
||||
{
|
||||
public bool Foo;
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new PredictionComponentState(Foo);
|
||||
}
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
[Reflect(false)]
|
||||
public sealed class PredictionTestEntitySystem : EntitySystem
|
||||
{
|
||||
if (curState is not PredictionComponentState state)
|
||||
return;
|
||||
|
||||
Foo = state.Foo;
|
||||
Dirty();
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
private sealed class PredictionComponentState : ComponentState
|
||||
{
|
||||
@@ -421,11 +411,7 @@ namespace Content.IntegrationTests.Tests.Networking
|
||||
Foo = foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Reflect(false)]
|
||||
public sealed class PredictionTestEntitySystem : EntitySystem
|
||||
{
|
||||
public bool Allow { get; set; } = true;
|
||||
|
||||
// Queue of all the events that come in so we can test that they come in perfectly as expected.
|
||||
@@ -440,6 +426,23 @@ namespace Content.IntegrationTests.Tests.Networking
|
||||
|
||||
SubscribeNetworkEvent<SetFooMessage>(HandleMessage);
|
||||
SubscribeLocalEvent<SetFooMessage>(HandleMessage);
|
||||
|
||||
SubscribeLocalEvent<PredictionTestComponent, ComponentGetState>(OnGetState);
|
||||
SubscribeLocalEvent<PredictionTestComponent, ComponentHandleState>(OnHandleState);
|
||||
}
|
||||
|
||||
private void OnHandleState(EntityUid uid, PredictionTestComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not PredictionComponentState state)
|
||||
return;
|
||||
|
||||
component.Foo = state.Foo;
|
||||
Dirty(component);
|
||||
}
|
||||
|
||||
private void OnGetState(EntityUid uid, PredictionTestComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new PredictionComponentState(component.Foo);
|
||||
}
|
||||
|
||||
private void HandleMessage(SetFooMessage message, EntitySessionEventArgs args)
|
||||
|
||||
@@ -8,25 +8,16 @@ namespace Content.Server.Chemistry.Components
|
||||
[RegisterComponent]
|
||||
public sealed class HyposprayComponent : SharedHyposprayComponent
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
|
||||
// TODO: This should be on clumsycomponent.
|
||||
[DataField("clumsyFailChance")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float ClumsyFailChance { get; set; } = 0.5f;
|
||||
public float ClumsyFailChance = 0.5f;
|
||||
|
||||
[DataField("transferAmount")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public FixedPoint2 TransferAmount { get; set; } = FixedPoint2.New(5);
|
||||
public FixedPoint2 TransferAmount = FixedPoint2.New(5);
|
||||
|
||||
[DataField("injectSound")]
|
||||
public SoundSpecifier InjectSound = new SoundPathSpecifier("/Audio/Items/hypospray.ogg");
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
var solutionSys = _entMan.EntitySysManager.GetEntitySystem<SolutionContainerSystem>();
|
||||
return solutionSys.TryGetSolution(Owner, SolutionName, out var solution)
|
||||
? new HyposprayComponentState(solution.Volume, solution.MaxVolume)
|
||||
: new HyposprayComponentState(FixedPoint2.Zero, FixedPoint2.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Linq;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
// using Content.Server.Weapons.Melee;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
@@ -12,6 +12,7 @@ using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Content.Shared.Timing;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
@@ -25,6 +26,14 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
SubscribeLocalEvent<HyposprayComponent, MeleeHitEvent>(OnAttack);
|
||||
SubscribeLocalEvent<HyposprayComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<HyposprayComponent, UseInHandEvent>(OnUseInHand);
|
||||
SubscribeLocalEvent<HyposprayComponent, ComponentGetState>(OnHypoGetState);
|
||||
}
|
||||
|
||||
private void OnHypoGetState(EntityUid uid, HyposprayComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = _solutions.TryGetSolution(uid, component.SolutionName, out var solution)
|
||||
? new HyposprayComponentState(solution.Volume, solution.MaxVolume)
|
||||
: new HyposprayComponentState(FixedPoint2.Zero, FixedPoint2.Zero);
|
||||
}
|
||||
|
||||
private void OnUseInHand(EntityUid uid, HyposprayComponent component, UseInHandEvent args)
|
||||
|
||||
@@ -2,8 +2,8 @@ using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Chemistry.Components
|
||||
{
|
||||
namespace Content.Shared.Chemistry.Components;
|
||||
|
||||
[NetworkedComponent()]
|
||||
public abstract class SharedHyposprayComponent : Component
|
||||
{
|
||||
@@ -23,4 +23,3 @@ namespace Content.Shared.Chemistry.Components
|
||||
MaxVolume = maxVolume;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +1,15 @@
|
||||
using Content.Shared.Item;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Hands.Components;
|
||||
|
||||
namespace Content.Shared.Hands.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent]
|
||||
public sealed class HandVirtualItemComponent : Component
|
||||
[AutoGenerateComponentState(true)]
|
||||
public sealed partial class HandVirtualItemComponent : Component
|
||||
{
|
||||
private EntityUid _blockingEntity;
|
||||
|
||||
/// <summary>
|
||||
/// The entity blocking this hand.
|
||||
/// </summary>
|
||||
public EntityUid BlockingEntity
|
||||
{
|
||||
get => _blockingEntity;
|
||||
set
|
||||
{
|
||||
_blockingEntity = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new VirtualItemComponentState(BlockingEntity);
|
||||
}
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
if (curState is not VirtualItemComponentState pullState)
|
||||
return;
|
||||
|
||||
_blockingEntity = pullState.BlockingEntity;
|
||||
|
||||
// update hands GUI with new entity.
|
||||
if (Owner.TryGetContainer(out _))
|
||||
EntitySystem.Get<SharedItemSystem>().VisualsChanged(Owner);
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class VirtualItemComponentState : ComponentState
|
||||
{
|
||||
public readonly EntityUid BlockingEntity;
|
||||
|
||||
public VirtualItemComponentState(EntityUid blockingEntity)
|
||||
{
|
||||
BlockingEntity = blockingEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
[DataField("blockingEntity"), AutoNetworkedField]
|
||||
public EntityUid BlockingEntity;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Content.Shared.Hands.Components;
|
||||
|
||||
namespace Content.Shared.Hands.EntitySystems;
|
||||
|
||||
public abstract partial class SharedHandsSystem
|
||||
{
|
||||
private void InitializeVirtual()
|
||||
{
|
||||
SubscribeLocalEvent<HandVirtualItemComponent, AfterAutoHandleStateEvent>(OnVirtualAfter);
|
||||
}
|
||||
|
||||
private void OnVirtualAfter(EntityUid uid, HandVirtualItemComponent component, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
// update hands GUI with new entity.
|
||||
if (_containerSystem.IsEntityInContainer(uid))
|
||||
_items.VisualsChanged(uid);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Item;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Input.Binding;
|
||||
|
||||
@@ -12,9 +13,10 @@ namespace Content.Shared.Hands.EntitySystems;
|
||||
public abstract partial class SharedHandsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||
[Dependency] private readonly SharedItemSystem _items = default!;
|
||||
|
||||
protected event Action<HandsComponent?>? OnHandSetActive;
|
||||
|
||||
@@ -25,6 +27,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
InitializeInteractions();
|
||||
InitializeDrop();
|
||||
InitializePickup();
|
||||
InitializeVirtual();
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
|
||||
@@ -37,6 +37,7 @@ public abstract class SharedHandVirtualItemSystem : EntitySystem
|
||||
virtualItem = Spawn("HandVirtualItem", pos);
|
||||
var virtualItemComp = EntityManager.GetComponent<HandVirtualItemComponent>(virtualItem.Value);
|
||||
virtualItemComp.BlockingEntity = blockingEnt;
|
||||
Dirty(virtualItemComp);
|
||||
_hands.DoPickup(user, hand, virtualItem.Value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Alert;
|
||||
using Content.Shared.Alert;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
@@ -33,6 +34,7 @@ namespace Content.Tests.Shared.Alert
|
||||
// but wanted to keep it anyway to see what's possible w.r.t. testing components
|
||||
// in a unit test
|
||||
|
||||
var entManager = IoCManager.Resolve<IEntityManager>();
|
||||
IoCManager.Resolve<ISerializationManager>().Initialize();
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
prototypeManager.Initialize();
|
||||
@@ -41,7 +43,7 @@ namespace Content.Tests.Shared.Alert
|
||||
prototypeManager.LoadFromStream(new StringReader(PROTOTYPES));
|
||||
prototypeManager.ResolveResults();
|
||||
|
||||
var entSys = IoCManager.Resolve<IEntitySystemManager>();
|
||||
var entSys = entManager.EntitySysManager;
|
||||
entSys.LoadExtraSystemType<ServerAlertsSystem>();
|
||||
|
||||
var alertsComponent = new AlertsComponent();
|
||||
@@ -51,18 +53,27 @@ namespace Content.Tests.Shared.Alert
|
||||
Assert.That(EntitySystem.Get<AlertsSystem>().TryGet(AlertType.HighPressure, out var highpressure));
|
||||
|
||||
EntitySystem.Get<AlertsSystem>().ShowAlert(alertsComponent.Owner, AlertType.LowPressure, null, null);
|
||||
var alertState = alertsComponent.GetComponentState() as AlertsComponentState;
|
||||
|
||||
var getty = new ComponentGetState();
|
||||
entManager.EventBus.RaiseComponentEvent(alertsComponent, getty);
|
||||
|
||||
var alertState = (AlertsComponentState) getty.State!;
|
||||
Assert.NotNull(alertState);
|
||||
Assert.That(alertState.Alerts.Count, Is.EqualTo(1));
|
||||
Assert.That(alertState.Alerts.ContainsKey(lowpressure.AlertKey));
|
||||
|
||||
EntitySystem.Get<AlertsSystem>().ShowAlert(alertsComponent.Owner, AlertType.HighPressure, null, null);
|
||||
alertState = alertsComponent.GetComponentState() as AlertsComponentState;
|
||||
|
||||
// Lazy
|
||||
entManager.EventBus.RaiseComponentEvent(alertsComponent, getty);
|
||||
alertState = (AlertsComponentState) getty.State!;
|
||||
Assert.That(alertState.Alerts.Count, Is.EqualTo(1));
|
||||
Assert.That(alertState.Alerts.ContainsKey(highpressure.AlertKey));
|
||||
|
||||
EntitySystem.Get<AlertsSystem>().ClearAlertCategory(alertsComponent.Owner, AlertCategory.Pressure);
|
||||
alertState = alertsComponent.GetComponentState() as AlertsComponentState;
|
||||
|
||||
entManager.EventBus.RaiseComponentEvent(alertsComponent, getty);
|
||||
alertState = (AlertsComponentState) getty.State!;
|
||||
Assert.That(alertState.Alerts.Count, Is.EqualTo(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,7 @@ namespace Content.Tests.Shared.Gamestates
|
||||
foreach (var compType in comps)
|
||||
{
|
||||
// Any component should be able to be instantiated without DI injection.
|
||||
var compInstance = (IComponent) Activator.CreateInstance(compType);
|
||||
|
||||
// Any component should treat this as a null function.
|
||||
compInstance.HandleComponentState(null, null);
|
||||
_ = (IComponent) Activator.CreateInstance(compType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user