Slay bobby pt. 1 (#5632)

This commit is contained in:
mirrorcult
2021-12-01 03:44:34 -07:00
committed by GitHub
parent 21f9a62655
commit 53c0a47e39
18 changed files with 12 additions and 977 deletions

View File

@@ -1,207 +0,0 @@
#nullable enable
using System.Linq;
using System.Threading.Tasks;
using Content.Server.Body.Behavior;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using NUnit.Framework;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Content.IntegrationTests.Tests.Body
{
[TestFixture]
[TestOf(typeof(SharedBodyComponent))]
[TestOf(typeof(SharedBodyPartComponent))]
[TestOf(typeof(SharedMechanismComponent))]
[TestOf(typeof(MechanismBehavior))]
public class MechanismBehaviorEventsTest : ContentIntegrationTest
{
private class TestMechanismBehavior : MechanismBehavior
{
public bool WasAddedToBody;
public bool WasAddedToPart;
public bool WasAddedToPartInBody;
public bool WasRemovedFromBody;
public bool WasRemovedFromPart;
public bool WasRemovedFromPartInBody;
public bool NoAdded()
{
return !WasAddedToBody && !WasAddedToPart && !WasAddedToPartInBody;
}
public bool NoRemoved()
{
return !WasRemovedFromBody && !WasRemovedFromPart && !WasRemovedFromPartInBody;
}
public void ResetAdded()
{
WasAddedToBody = false;
WasAddedToPart = false;
WasAddedToPartInBody = false;
}
public void ResetRemoved()
{
WasRemovedFromBody = false;
WasRemovedFromPart = false;
WasRemovedFromPartInBody = false;
}
public void ResetAll()
{
ResetAdded();
ResetRemoved();
}
protected override void OnAddedToBody(SharedBodyComponent body)
{
base.OnAddedToBody(body);
WasAddedToBody = true;
}
protected override void OnAddedToPart(SharedBodyPartComponent part)
{
base.OnAddedToPart(part);
WasAddedToPart = true;
}
protected override void OnAddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part)
{
base.OnAddedToPartInBody(body, part);
WasAddedToPartInBody = true;
}
protected override void OnRemovedFromBody(SharedBodyComponent old)
{
base.OnRemovedFromBody(old);
WasRemovedFromBody = true;
}
protected override void OnRemovedFromPart(SharedBodyPartComponent old)
{
base.OnRemovedFromPart(old);
WasRemovedFromPart = true;
}
protected override void OnRemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart)
{
base.OnRemovedFromPartInBody(oldBody, oldPart);
WasRemovedFromPartInBody = true;
}
}
private const string Prototypes = @"
- type: entity
name: HumanBodyDummy
id: HumanBodyDummy
components:
- type: Body
template: HumanoidTemplate
preset: HumanPreset
centerSlot: torso
";
[Test]
public async Task EventsTest()
{
var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes};
var server = StartServer(options);
await server.WaitAssertion(() =>
{
var mapManager = IoCManager.Resolve<IMapManager>();
var mapId = mapManager.CreateMap();
var entityManager = IoCManager.Resolve<IEntityManager>();
var human = entityManager.SpawnEntity("HumanBodyDummy", new MapCoordinates(Vector2.Zero, mapId));
Assert.That(human.TryGetComponent(out SharedBodyComponent? body));
Assert.NotNull(body);
var centerPart = body!.CenterPart;
Assert.NotNull(centerPart);
Assert.That(body.TryGetSlot(centerPart!, out var centerSlot));
Assert.NotNull(centerSlot);
var mechanism = centerPart!.Mechanisms.First();
Assert.NotNull(mechanism);
mechanism.EnsureBehavior<TestMechanismBehavior>(out var behavior);
Assert.False(behavior.WasAddedToBody);
Assert.False(behavior.WasAddedToPart);
Assert.That(behavior.WasAddedToPartInBody);
Assert.That(behavior.NoRemoved);
behavior.ResetAll();
Assert.That(behavior.NoAdded);
Assert.That(behavior.NoRemoved);
centerPart.RemoveMechanism(mechanism);
Assert.That(behavior.NoAdded);
Assert.False(behavior.WasRemovedFromBody);
Assert.False(behavior.WasRemovedFromPart);
Assert.That(behavior.WasRemovedFromPartInBody);
behavior.ResetAll();
centerPart.TryAddMechanism(mechanism, true);
Assert.False(behavior.WasAddedToBody);
Assert.False(behavior.WasAddedToPart);
Assert.That(behavior.WasAddedToPartInBody);
Assert.That(behavior.NoRemoved());
behavior.ResetAll();
body.RemovePart(centerPart);
Assert.That(behavior.NoAdded);
Assert.That(behavior.WasRemovedFromBody);
Assert.False(behavior.WasRemovedFromPart);
Assert.False(behavior.WasRemovedFromPartInBody);
behavior.ResetAll();
centerPart.RemoveMechanism(mechanism);
Assert.That(behavior.NoAdded);
Assert.False(behavior.WasRemovedFromBody);
Assert.That(behavior.WasRemovedFromPart);
Assert.False(behavior.WasRemovedFromPartInBody);
behavior.ResetAll();
centerPart.TryAddMechanism(mechanism, true);
Assert.False(behavior.WasAddedToBody);
Assert.That(behavior.WasAddedToPart);
Assert.False(behavior.WasAddedToPartInBody);
Assert.That(behavior.NoRemoved);
behavior.ResetAll();
body.SetPart(centerSlot!.Id, centerPart);
Assert.That(behavior.WasAddedToBody);
Assert.False(behavior.WasAddedToPart);
Assert.False(behavior.WasAddedToPartInBody);
Assert.That(behavior.NoRemoved);
});
}
}
}

View File

@@ -1,109 +0,0 @@
using Content.Shared.Body.Behavior;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
using Robust.Shared.Utility;
namespace Content.Server.Body.Behavior
{
public abstract class MechanismBehavior : SharedMechanismBehavior
{
private SharedMechanismComponent _parent = default!;
public override SharedBodyComponent? Body => Part?.Body;
public override SharedBodyPartComponent? Part => Parent.Part;
public override SharedMechanismComponent Parent => _parent;
public override IEntity Owner => Parent.Owner;
public override void Initialize(SharedMechanismComponent parent)
{
_parent = parent;
}
public override void Startup()
{
if (Part == null)
{
return;
}
if (Body == null)
{
AddedToPart(Part);
}
else
{
AddedToPartInBody(Body, Part);
}
}
public override void Update(float frameTime) { }
public override void AddedToBody(SharedBodyComponent body)
{
DebugTools.AssertNotNull(Body);
DebugTools.AssertNotNull(body);
OnAddedToBody(body);
}
public override void AddedToPart(SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(Part);
DebugTools.AssertNotNull(part);
OnAddedToPart(part);
}
public override void AddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(Body);
DebugTools.AssertNotNull(body);
DebugTools.AssertNotNull(Part);
DebugTools.AssertNotNull(part);
OnAddedToPartInBody(body, part);
}
public override void RemovedFromBody(SharedBodyComponent old)
{
DebugTools.AssertNull(Body);
DebugTools.AssertNotNull(old);
OnRemovedFromBody(old);
}
public override void RemovedFromPart(SharedBodyPartComponent old)
{
DebugTools.AssertNull(Part);
DebugTools.AssertNotNull(old);
OnRemovedFromPart(old);
}
public override void RemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart)
{
DebugTools.AssertNull(Body);
DebugTools.AssertNull(Part);
DebugTools.AssertNotNull(oldBody);
DebugTools.AssertNotNull(oldPart);
OnRemovedFromPartInBody(oldBody, oldPart);
}
protected virtual void OnAddedToBody(SharedBodyComponent body) { }
protected virtual void OnAddedToPart(SharedBodyPartComponent part) { }
protected virtual void OnAddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part) { }
protected virtual void OnRemovedFromBody(SharedBodyComponent old) { }
protected virtual void OnRemovedFromPart(SharedBodyPartComponent old) { }
protected virtual void OnRemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart) { }
}
}

View File

@@ -1,26 +1,9 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Alert;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Behavior;
using Content.Server.Body.Systems; using Content.Server.Body.Systems;
using Content.Server.Temperature.Components;
using Content.Server.Temperature.Systems;
using Content.Shared.ActionBlocker;
using Content.Shared.Administration.Logs;
using Content.Shared.Alert;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Body.Components;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.MobState.Components;
using Content.Shared.Popups;
using Robust.Shared.Analyzers; using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;

View File

@@ -1,117 +0,0 @@
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Behavior
{
/// <summary>
/// Gives functionality to a mechanism when added to it.
/// </summary>
[ImplicitDataDefinitionForInheritors]
public abstract class SharedMechanismBehavior
{
public abstract SharedBodyComponent? Body { get; }
public abstract SharedBodyPartComponent? Part { get; }
public abstract SharedMechanismComponent Parent { get; }
/// <summary>
/// The entity that owns <see cref="Parent"/>.
/// For the entity owning the body that this mechanism may be in,
/// see <see cref="Body"/>'s <see cref="SharedBodyComponent.Owner"/>.
/// </summary>
public abstract IEntity Owner { get; }
/// <summary>
/// Called when this behavior is added to a mechanism, during <see cref="IComponent.Initialize"/>.
/// If it is added after component initialization,
/// it is called immediately.
/// </summary>
/// <param name="parent">
/// The mechanism that owns this behavior.
/// </param>
public abstract void Initialize(SharedMechanismComponent parent);
/// <summary>
/// Called when this behavior is added to a mechanism, during <see cref="Component.Startup"/>.
/// If it is added after component startup, it is called immediately.
/// </summary>
public abstract void Startup();
/// <summary>
/// Runs an update cycle on this behavior.
/// </summary>
/// <param name="frameTime">
/// The amount of seconds that passed since the last update.
/// </param>
public abstract void Update(float frameTime);
/// <summary>
/// Called when the containing part is attached to a body.
/// For instance, attaching a head with a brain inside to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="body">
/// The body that the containing mechanism was added to.
/// </param>
public abstract void AddedToBody(SharedBodyComponent body);
/// <summary>
/// Called when the parent mechanism is added into a part that is not attached to a body.
/// For instance, adding a brain to a dismembered head.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="part">
/// The part that the containing mechanism was added to.
/// </param>
public abstract void AddedToPart(SharedBodyPartComponent part);
/// <summary>
/// Called when the parent mechanism is added to a part that is attached to a body.
/// For instance, adding a brain to a head that is attached to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="body">
/// The body that the containing mechanism was added to.
/// </param>
/// <param name="part">
/// The part that the containing mechanism was added to.
/// </param>
public abstract void AddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part);
/// <summary>
/// Called when the parent part is removed from a body.
/// For instance, removing a head with a brain inside from a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="old">
/// The body that the containing mechanism was removed from.
/// </param>
public abstract void RemovedFromBody(SharedBodyComponent old);
/// <summary>
/// Called when the parent mechanism is removed from a part that is not attached to a body.
/// For instance, removing a brain from a dismembered head.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="old">
/// The part that the containing mechanism was removed from.
/// </param>
public abstract void RemovedFromPart(SharedBodyPartComponent old);
/// <summary>
/// Called when the parent mechanism is removed from a part that is attached to a body.
/// For instance, removing a brain from a head that is attached to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="oldBody">
/// The body that the containing mechanism was removed from.
/// </param>
/// <param name="oldPart">
/// The part that the containing mechanism was removed from.
/// </param>
public abstract void RemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart);
}
}

View File

@@ -2,19 +2,15 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Shared.Body.Behavior;
using Content.Shared.Body.Part; using Content.Shared.Body.Part;
using Content.Shared.Body.Part.Property;
using Content.Shared.Body.Prototypes; using Content.Shared.Body.Prototypes;
using Content.Shared.CharacterAppearance.Systems; using Content.Shared.CharacterAppearance.Systems;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes; using Content.Shared.Damage.Prototypes;
using Content.Shared.Movement.Components;
using Content.Shared.Standing; using Content.Shared.Standing;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Players;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
@@ -34,11 +30,11 @@ namespace Content.Shared.Body.Components
[ViewVariables] [ViewVariables]
[DataField("template", required: true)] [DataField("template", required: true)]
private string? TemplateId { get; } = default; private string? TemplateId { get; }
[ViewVariables] [ViewVariables]
[DataField("preset", required: true)] [DataField("preset", required: true)]
private string? PresetId { get; } = default; private string? PresetId { get; }
[ViewVariables] [ViewVariables]
public BodyTemplatePrototype? Template => TemplateId == null public BodyTemplatePrototype? Template => TemplateId == null
@@ -449,93 +445,11 @@ namespace Content.Shared.Body.Components
} }
} }
/// <returns>A list of parts with that property.</returns>
public IEnumerable<(SharedBodyPartComponent part, IBodyPartProperty property)> GetPartsWithProperty(Type type)
{
foreach (var slot in SlotIds.Values)
{
if (slot.Part != null && slot.Part.TryGetProperty(type, out var property))
{
yield return (slot.Part, property);
}
}
}
public IEnumerable<(SharedBodyPartComponent part, T property)> GetPartsWithProperty<T>() where T : class, IBodyPartProperty
{
foreach (var part in SlotParts.Keys)
{
if (part.TryGetProperty<T>(out var property))
{
yield return (part, property);
}
}
}
private void OnBodyChanged() private void OnBodyChanged()
{ {
Dirty(); Dirty();
} }
public float DistanceToNearestFoot(SharedBodyPartComponent source)
{
if (source.PartType == BodyPartType.Foot &&
source.TryGetProperty<ExtensionComponent>(out var extension))
{
return extension.Distance;
}
return LookForFootRecursion(source);
}
private float LookForFootRecursion(SharedBodyPartComponent current, HashSet<BodyPartSlot>? searched = null)
{
searched ??= new HashSet<BodyPartSlot>();
if (!current.TryGetProperty<ExtensionComponent>(out var extProperty))
{
return float.MinValue;
}
if (!TryGetSlot(current, out var slot))
{
return float.MinValue;
}
foreach (var connection in slot.Connections)
{
if (connection.PartType == BodyPartType.Foot &&
!searched.Contains(connection))
{
return extProperty.Distance;
}
}
var distances = new List<float>();
foreach (var connection in slot.Connections)
{
if (connection.Part == null || !searched.Contains(connection))
{
continue;
}
var result = LookForFootRecursion(connection.Part, searched);
if (Math.Abs(result - float.MinValue) > 0.001f)
{
distances.Add(result);
}
}
if (distances.Count > 0)
{
return distances.Min<float>() + extProperty.Distance;
}
return float.MinValue;
}
// TODO BODY optimize this // TODO BODY optimize this
public BodyPartSlot SlotAt(int index) public BodyPartSlot SlotAt(int index)
{ {
@@ -601,62 +515,6 @@ namespace Content.Shared.Body.Components
part.Gib(); part.Gib();
} }
} }
public bool TryGetMechanismBehaviors([NotNullWhen(true)] out List<SharedMechanismBehavior>? behaviors)
{
behaviors = GetMechanismBehaviors().ToList();
if (behaviors.Count == 0)
{
behaviors = null;
return false;
}
return true;
}
public bool HasMechanismBehavior<T>() where T : SharedMechanismBehavior
{
return Parts.Any(p => p.Key.HasMechanismBehavior<T>());
}
// TODO cache these 2 methods jesus
public IEnumerable<SharedMechanismBehavior> GetMechanismBehaviors()
{
foreach (var (part, _) in Parts)
foreach (var mechanism in part.Mechanisms)
foreach (var behavior in mechanism.Behaviors.Values)
{
yield return behavior;
}
}
public IEnumerable<T> GetMechanismBehaviors<T>() where T : SharedMechanismBehavior
{
foreach (var (part, _) in Parts)
foreach (var mechanism in part.Mechanisms)
foreach (var behavior in mechanism.Behaviors.Values)
{
if (behavior is T tBehavior)
{
yield return tBehavior;
}
}
}
public bool TryGetMechanismBehaviors<T>([NotNullWhen(true)] out List<T>? behaviors)
where T : SharedMechanismBehavior
{
behaviors = GetMechanismBehaviors<T>().ToList();
if (behaviors.Count == 0)
{
behaviors = null;
return false;
}
return true;
}
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]

View File

@@ -1,16 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Shared.Body.Behavior; using Content.Shared.Body.Events;
using Content.Shared.Body.Part; using Content.Shared.Body.Part;
using Content.Shared.Body.Part.Property;
using Content.Shared.Body.Surgery; using Content.Shared.Body.Surgery;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Players;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -307,7 +304,7 @@ namespace Content.Shared.Body.Components
foreach (var mechanism in _mechanisms) foreach (var mechanism in _mechanisms)
{ {
mechanism.AddedToBody(body); Owner.EntityManager.EventBus.RaiseLocalEvent(mechanism.OwnerUid, new AddedToBodyEvent(body));
} }
} }
@@ -322,7 +319,7 @@ namespace Content.Shared.Body.Components
foreach (var mechanism in _mechanisms) foreach (var mechanism in _mechanisms)
{ {
mechanism.RemovedFromBody(old); Owner.EntityManager.EventBus.RaiseLocalEvent(mechanism.OwnerUid, new RemovedFromBodyEvent(old));
} }
} }
@@ -340,38 +337,6 @@ namespace Content.Shared.Body.Components
RemoveMechanism(mechanism); RemoveMechanism(mechanism);
} }
} }
public bool HasProperty(Type type)
{
return Owner.HasComponent(type);
}
public bool HasProperty<T>() where T : class, IBodyPartProperty
{
return HasProperty(typeof(T));
}
public bool TryGetProperty(Type type,
[NotNullWhen(true)] out IBodyPartProperty? property)
{
if (!Owner.TryGetComponent(type, out var component))
{
property = null;
return false;
}
return (property = component as IBodyPartProperty) != null;
}
public bool TryGetProperty<T>([NotNullWhen(true)] out T? property) where T : class, IBodyPartProperty
{
return Owner.TryGetComponent(out property);
}
public bool HasMechanismBehavior<T>() where T : SharedMechanismBehavior
{
return Mechanisms.Any(m => m.HasBehavior<T>());
}
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]

View File

@@ -1,15 +1,9 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Body.Behavior;
using Content.Shared.Body.Events; using Content.Shared.Body.Events;
using Content.Shared.Body.Part; using Content.Shared.Body.Part;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.Body.Components namespace Content.Shared.Body.Components
{ {
@@ -23,10 +17,6 @@ namespace Content.Shared.Body.Components
protected IEntity? PerformerCache; protected IEntity? PerformerCache;
private SharedBodyPartComponent? _part; private SharedBodyPartComponent? _part;
[DataField("behaviors", serverOnly: true)] private HashSet<SharedMechanismBehavior> _behaviorTypes = new();
private readonly Dictionary<Type, SharedMechanismBehavior> _behaviors = new();
public SharedBodyComponent? Body => Part?.Body; public SharedBodyComponent? Body => Part?.Body;
public SharedBodyPartComponent? Part public SharedBodyPartComponent? Part
@@ -46,11 +36,11 @@ namespace Content.Shared.Body.Components
{ {
if (old.Body == null) if (old.Body == null)
{ {
RemovedFromPart(old); Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, new RemovedFromPartEvent(old));
} }
else else
{ {
RemovedFromPartInBody(old.Body, old); Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, new RemovedFromPartInBodyEvent(old.Body, old));
} }
} }
@@ -58,18 +48,16 @@ namespace Content.Shared.Body.Components
{ {
if (value.Body == null) if (value.Body == null)
{ {
AddedToPart(value); Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, new AddedToPartEvent(value));
} }
else else
{ {
AddedToPartInBody(value.Body, value); Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, new AddedToPartInBodyEvent(value.Body, value));
} }
} }
} }
} }
public IReadOnlyDictionary<Type, SharedMechanismBehavior> Behaviors => _behaviors;
[DataField("maxDurability")] public int MaxDurability { get; set; } = 10; [DataField("maxDurability")] public int MaxDurability { get; set; } = 10;
[DataField("currentDurability")] public int CurrentDurability { get; set; } = 10; [DataField("currentDurability")] public int CurrentDurability { get; set; } = 10;
@@ -93,176 +81,5 @@ namespace Content.Shared.Body.Components
/// </summary> /// </summary>
[DataField("compatibility")] [DataField("compatibility")]
public BodyPartCompatibility Compatibility { get; set; } = BodyPartCompatibility.Universal; public BodyPartCompatibility Compatibility { get; set; } = BodyPartCompatibility.Universal;
void ISerializationHooks.BeforeSerialization()
{
_behaviorTypes = _behaviors.Values.ToHashSet();
}
void ISerializationHooks.AfterDeserialization()
{
foreach (var behavior in _behaviorTypes)
{
var type = behavior.GetType();
if (!_behaviors.TryAdd(type, behavior))
{
Logger.Warning($"Duplicate behavior in {nameof(SharedMechanismComponent)}: {type}.");
continue;
}
IoCManager.InjectDependencies(behavior);
}
}
protected override void Initialize()
{
base.Initialize();
foreach (var behavior in _behaviors.Values)
{
behavior.Initialize(this);
}
}
protected override void Startup()
{
base.Startup();
foreach (var behavior in _behaviors.Values)
{
behavior.Startup();
}
}
public bool EnsureBehavior<T>(out T behavior) where T : SharedMechanismBehavior, new()
{
if (_behaviors.TryGetValue(typeof(T), out var rawBehavior))
{
behavior = (T) rawBehavior;
return true;
}
behavior = IoCManager.Resolve<IDynamicTypeFactory>().CreateInstance<T>();
_behaviors.Add(typeof(T), behavior);
behavior.Initialize(this);
behavior.Startup();
return false;
}
public bool HasBehavior<T>() where T : SharedMechanismBehavior
{
return _behaviors.ContainsKey(typeof(T));
}
public bool TryRemoveBehavior<T>() where T : SharedMechanismBehavior
{
return _behaviors.Remove(typeof(T));
}
public void Update(float frameTime)
{
foreach (var behavior in _behaviors.Values)
{
behavior.Update(frameTime);
}
}
public void AddedToBody(SharedBodyComponent body)
{
DebugTools.AssertNotNull(Body);
DebugTools.AssertNotNull(body);
var ev = new AddedToBodyEvent(body);
Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, ev, false);
foreach (var behavior in _behaviors.Values)
{
behavior.AddedToBody(body);
}
}
public void AddedToPart(SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(Part);
DebugTools.AssertNotNull(part);
Owner.Transform.AttachParent(part.Owner);
var ev = new AddedToPartEvent(part);
Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, ev, false);
foreach (var behavior in _behaviors.Values)
{
behavior.AddedToPart(part);
}
}
public void AddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(Body);
DebugTools.AssertNotNull(body);
DebugTools.AssertNotNull(Part);
DebugTools.AssertNotNull(part);
Owner.Transform.AttachParent(part.Owner);
var ev = new AddedToPartInBodyEvent(body, part);
Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, ev, false);
foreach (var behavior in _behaviors.Values)
{
behavior.AddedToPartInBody(body, part);
}
}
public void RemovedFromBody(SharedBodyComponent old)
{
DebugTools.AssertNull(Body);
DebugTools.AssertNotNull(old);
var ev = new RemovedFromBodyEvent(old);
Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, ev, false);
foreach (var behavior in _behaviors.Values)
{
behavior.RemovedFromBody(old);
}
}
public void RemovedFromPart(SharedBodyPartComponent old)
{
DebugTools.AssertNull(Part);
DebugTools.AssertNotNull(old);
Owner.Transform.AttachToGridOrMap();
var ev = new RemovedFromPartEvent(old);
Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, ev, false);
foreach (var behavior in _behaviors.Values)
{
behavior.RemovedFromPart(old);
}
}
public void RemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart)
{
DebugTools.AssertNull(Body);
DebugTools.AssertNotNull(oldBody);
DebugTools.AssertNull(Part);
DebugTools.AssertNotNull(oldPart);
Owner.Transform.AttachToGridOrMap();
var ev = new RemovedFromPartInBodyEvent(oldBody, oldPart);
Owner.EntityManager.EventBus.RaiseLocalEvent(OwnerUid, ev, false);
foreach (var behavior in _behaviors.Values)
{
behavior.RemovedFromPartInBody(oldBody, oldPart);
}
}
} }
} }

View File

@@ -4,7 +4,7 @@ using Content.Shared.Body.Components;
using Content.Shared.Body.Part; using Content.Shared.Body.Part;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
namespace Content.Shared.Body namespace Content.Shared.Body.Part
{ {
public class BodyPartSlot public class BodyPartSlot
{ {

View File

@@ -1,21 +0,0 @@
using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Property attachable to a <see cref="SharedBodyPartComponent"/>.
/// For example, this is used to define the speed capabilities of a leg.
/// The movement system will look for a <see cref="LegComponent"/> on all
/// <see cref="SharedBodyPartComponent"/>.
/// </summary>
public abstract class BodyPartPropertyComponent : Component, IBodyPartProperty
{
/// <summary>
/// Whether this property is currently active.
/// </summary>
[DataField("active")]
public bool Active { get; set; } = true;
}
}

View File

@@ -1,21 +0,0 @@
using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Defines the length of a <see cref="SharedBodyPartComponent"/>.
/// </summary>
[RegisterComponent]
public class ExtensionComponent : BodyPartPropertyComponent
{
public override string Name => "Extension";
/// <summary>
/// Current distance in tiles.
/// </summary>
[DataField("distance")]
public float Distance { get; set; } = 3f;
}
}

View File

@@ -1,16 +0,0 @@
using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Defines a <see cref="SharedBodyPartComponent"/> as being able to grasp around an entity,
/// for example picking up an item.
/// </summary>
// TODO BODY Implement
[RegisterComponent]
public class GraspComponent : BodyPartPropertyComponent
{
public override string Name => "Grasp";
}
}

View File

@@ -1,13 +0,0 @@
using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Defines a property for a <see cref="SharedBodyPartComponent"/>.
/// </summary>
public interface IBodyPartProperty : IComponent
{
bool Active { get; set; }
}
}

View File

@@ -1,21 +0,0 @@
using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Defines the speed at which a <see cref="SharedBodyPartComponent"/> can move.
/// </summary>
[RegisterComponent]
public class LegComponent : BodyPartPropertyComponent
{
public override string Name => "Leg";
/// <summary>
/// Speed in tiles per second.
/// </summary>
[DataField("speed")]
public float Speed { get; set; } = 2.6f;
}
}

View File

@@ -1,20 +0,0 @@
using Content.Shared.Body.Components;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Systems
{
[UsedImplicitly]
public class MechanismSystem : EntitySystem
{
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var mechanism in EntityManager.EntityQuery<SharedMechanismComponent>(true))
{
mechanism.Update(frameTime);
}
}
}
}

View File

@@ -24,7 +24,6 @@
size: 1 size: 1
compatibility: Biological compatibility: Biological
symmetry: Left symmetry: Left
- type: Grasp
- type: entity - type: entity
id: LegsAnimal id: LegsAnimal

View File

@@ -83,8 +83,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 40 # criticalThreshold: 40
# deadThreshold: 80 # deadThreshold: 80
- type: Extension
distance: 2.4
- type: entity - type: entity
id: RightArmHuman id: RightArmHuman
@@ -106,8 +104,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 40 # criticalThreshold: 40
# deadThreshold: 80 # deadThreshold: 80
- type: Extension
distance: 2.4
- type: entity - type: entity
id: LeftHandHuman id: LeftHandHuman
@@ -129,7 +125,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 30 # criticalThreshold: 30
# deadThreshold: 60 # deadThreshold: 60
- type: Grasp
- type: entity - type: entity
id: RightHandHuman id: RightHandHuman
@@ -151,7 +146,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 30 # criticalThreshold: 30
# deadThreshold: 60 # deadThreshold: 60
- type: Grasp
- type: entity - type: entity
id: LeftLegHuman id: LeftLegHuman
@@ -173,10 +167,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 45 # criticalThreshold: 45
# deadThreshold: 90 # deadThreshold: 90
- type: Leg
speed: 2.6
- type: Extension
distance: 3.0
- type: entity - type: entity
id: RightLegHuman id: RightLegHuman
@@ -198,10 +188,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 45 # criticalThreshold: 45
# deadThreshold: 90 # deadThreshold: 90
- type: Leg
speed: 2.6
- type: Extension
distance: 3.0
- type: entity - type: entity
id: LeftFootHuman id: LeftFootHuman

View File

@@ -82,8 +82,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 40 # criticalThreshold: 40
# deadThreshold: 80 # deadThreshold: 80
- type: Extension
distance: 2.4
- type: entity - type: entity
id: RightArmSlime id: RightArmSlime
@@ -105,8 +103,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 40 # criticalThreshold: 40
# deadThreshold: 80 # deadThreshold: 80
- type: Extension
distance: 2.4
- type: entity - type: entity
id: LeftHandSlime id: LeftHandSlime
@@ -128,7 +124,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 30 # criticalThreshold: 30
# deadThreshold: 60 # deadThreshold: 60
- type: Grasp
- type: entity - type: entity
id: RightHandSlime id: RightHandSlime
@@ -150,7 +145,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 30 # criticalThreshold: 30
# deadThreshold: 60 # deadThreshold: 60
- type: Grasp
- type: entity - type: entity
id: LeftLegSlime id: LeftLegSlime
@@ -170,10 +164,6 @@
compatibility: Biological compatibility: Biological
symmetry: Left symmetry: Left
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
- type: Leg
speed: 2.6
- type: Extension
distance: 3.0
- type: entity - type: entity
id: RightLegSlime id: RightLegSlime
@@ -195,10 +185,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 45 # criticalThreshold: 45
# deadThreshold: 90 # deadThreshold: 90
- type: Leg
speed: 2.6
- type: Extension
distance: 3.0
- type: entity - type: entity
id: LeftFootSlime id: LeftFootSlime

View File

@@ -84,8 +84,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 40 # criticalThreshold: 40
# deadThreshold: 80 # deadThreshold: 80
- type: Extension
distance: 2.4
- type: entity - type: entity
id: RightArmVox id: RightArmVox
@@ -107,8 +105,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 40 # criticalThreshold: 40
# deadThreshold: 80 # deadThreshold: 80
- type: Extension
distance: 2.4
- type: entity - type: entity
id: LeftHandVox id: LeftHandVox
@@ -130,7 +126,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 30 # criticalThreshold: 30
# deadThreshold: 60 # deadThreshold: 60
- type: Grasp
- type: entity - type: entity
id: RightHandVox id: RightHandVox
@@ -152,7 +147,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 30 # criticalThreshold: 30
# deadThreshold: 60 # deadThreshold: 60
- type: Grasp
- type: entity - type: entity
id: LeftLegVox id: LeftLegVox
@@ -174,10 +168,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 45 # criticalThreshold: 45
# deadThreshold: 90 # deadThreshold: 90
- type: Leg
speed: 2.6
- type: Extension
distance: 3.0
- type: entity - type: entity
id: RightLegVox id: RightLegVox
@@ -199,10 +189,6 @@
- type: BiologicalSurgeryData - type: BiologicalSurgeryData
# criticalThreshold: 45 # criticalThreshold: 45
# deadThreshold: 90 # deadThreshold: 90
- type: Leg
speed: 2.6
- type: Extension
distance: 3.0
- type: entity - type: entity
id: LeftFootVox id: LeftFootVox