Component ECS (#17991)

This commit is contained in:
metalgearsloth
2023-07-13 20:20:46 +10:00
committed by GitHub
parent 0c93be1dcd
commit fbf1d476f2
13 changed files with 108 additions and 114 deletions

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);
}
}
}

View File

@@ -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)

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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()

View File

@@ -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;
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}