Remove IBody, IBodyPart, IMechanism and IMechanismBehavior (#4187)
* Remove IBody, IBodyPart, IMechanism and IMechanismBehavior interfaces * Summary cleanup
This commit is contained in:
@@ -5,7 +5,7 @@ using Robust.Shared.GameObjects;
|
|||||||
namespace Content.Client.Body.Components
|
namespace Content.Client.Body.Components
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(IBody))]
|
[ComponentReference(typeof(SharedBodyComponent))]
|
||||||
public class BodyComponent : SharedBodyComponent, IDraggable
|
public class BodyComponent : SharedBodyComponent, IDraggable
|
||||||
{
|
{
|
||||||
bool IDraggable.CanStartDrag(StartDragDropEvent args)
|
bool IDraggable.CanStartDrag(StartDragDropEvent args)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace Content.Client.Body.Components
|
|||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(SharedBodyPartComponent))]
|
[ComponentReference(typeof(SharedBodyPartComponent))]
|
||||||
[ComponentReference(typeof(IBodyPart))]
|
|
||||||
public class BodyPartComponent : SharedBodyPartComponent
|
public class BodyPartComponent : SharedBodyPartComponent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace Content.Client.Body.Components
|
|||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(SharedMechanismComponent))]
|
[ComponentReference(typeof(SharedMechanismComponent))]
|
||||||
[ComponentReference(typeof(IMechanism))]
|
public class MechanismComponent : SharedMechanismComponent
|
||||||
public class MechanismComponent : SharedMechanismComponent { }
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ namespace Content.Client.Body.UI
|
|||||||
public sealed class BodyScannerDisplay : SS14Window
|
public sealed class BodyScannerDisplay : SS14Window
|
||||||
{
|
{
|
||||||
private IEntity? _currentEntity;
|
private IEntity? _currentEntity;
|
||||||
private IBodyPart? _currentBodyPart;
|
private SharedBodyPartComponent? _currentBodyPart;
|
||||||
|
|
||||||
private IBody? CurrentBody => _currentEntity?.GetComponentOrNull<IBody>();
|
private SharedBodyComponent? CurrentBody => _currentEntity?.GetComponentOrNull<SharedBodyComponent>();
|
||||||
|
|
||||||
public BodyScannerDisplay(BodyScannerBoundUserInterface owner)
|
public BodyScannerDisplay(BodyScannerBoundUserInterface owner)
|
||||||
{
|
{
|
||||||
@@ -137,7 +137,7 @@ namespace Content.Client.Body.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateBodyPartBox(IBodyPart part, string slotName)
|
private void UpdateBodyPartBox(SharedBodyPartComponent part, string slotName)
|
||||||
{
|
{
|
||||||
BodyPartLabel.Text = $"{Loc.GetString(slotName)}: {Loc.GetString(part.Owner.Name)}";
|
BodyPartLabel.Text = $"{Loc.GetString(slotName)}: {Loc.GetString(part.Owner.Name)}";
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ namespace Content.Client.Body.UI
|
|||||||
UpdateMechanismBox(_currentBodyPart?.Mechanisms.ElementAt(args.ItemIndex));
|
UpdateMechanismBox(_currentBodyPart?.Mechanisms.ElementAt(args.ItemIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMechanismBox(IMechanism? mechanism)
|
private void UpdateMechanismBox(SharedMechanismComponent? mechanism)
|
||||||
{
|
{
|
||||||
// TODO BODY Improve UI
|
// TODO BODY Improve UI
|
||||||
if (mechanism == null)
|
if (mechanism == null)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace Content.Client.CharacterAppearance
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out IBody? body))
|
if (Owner.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
foreach (var (part, _) in body.Parts)
|
foreach (var (part, _) in body.Parts)
|
||||||
{
|
{
|
||||||
@@ -115,7 +115,7 @@ namespace Content.Client.CharacterAppearance
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.Part.Owner.TryGetComponent(out SpriteComponent? partSprite))
|
if (!args.Part.Owner.HasComponent<SpriteComponent>())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -138,7 +138,7 @@ namespace Content.Client.CharacterAppearance
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.Part.Owner.TryGetComponent(out SpriteComponent? partSprite))
|
if (!args.Part.Owner.HasComponent<SpriteComponent>())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Content.Client.Commands
|
|||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
{
|
{
|
||||||
var componentManager = IoCManager.Resolve<IComponentManager>();
|
var componentManager = IoCManager.Resolve<IComponentManager>();
|
||||||
var mechanisms = componentManager.EntityQuery<IMechanism>(true);
|
var mechanisms = componentManager.EntityQuery<SharedMechanismComponent>(true);
|
||||||
|
|
||||||
foreach (var mechanism in mechanisms)
|
foreach (var mechanism in mechanisms)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Content.Client.Commands
|
|||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
{
|
{
|
||||||
var componentManager = IoCManager.Resolve<IComponentManager>();
|
var componentManager = IoCManager.Resolve<IComponentManager>();
|
||||||
var mechanisms = componentManager.EntityQuery<IMechanism>(true);
|
var mechanisms = componentManager.EntityQuery<SharedMechanismComponent>(true);
|
||||||
|
|
||||||
foreach (var mechanism in mechanisms)
|
foreach (var mechanism in mechanisms)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||||
var human = entityManager.SpawnEntity("HumanBodyAndAppearanceDummy", new MapCoordinates(Vector2.Zero, mapId));
|
var human = entityManager.SpawnEntity("HumanBodyAndAppearanceDummy", new MapCoordinates(Vector2.Zero, mapId));
|
||||||
|
|
||||||
Assert.That(human.TryGetComponent(out IBody body));
|
Assert.That(human.TryGetComponent(out SharedBodyComponent body));
|
||||||
Assert.That(human.TryGetComponent(out appearance));
|
Assert.That(human.TryGetComponent(out appearance));
|
||||||
|
|
||||||
Assert.That(!appearance.TryGetData(RotationVisuals.RotationState, out RotationState _));
|
Assert.That(!appearance.TryGetData(RotationVisuals.RotationState, out RotationState _));
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
|
|
||||||
var human = entityManager.SpawnEntity("HumanBodyAndBloodstreamDummy", new MapCoordinates(Vector2.Zero, mapId));
|
var human = entityManager.SpawnEntity("HumanBodyAndBloodstreamDummy", new MapCoordinates(Vector2.Zero, mapId));
|
||||||
|
|
||||||
Assert.That(human.TryGetComponent(out IBody body));
|
Assert.That(human.TryGetComponent(out SharedBodyComponent body));
|
||||||
Assert.That(body.TryGetMechanismBehaviors(out List<LungBehavior> lungs));
|
Assert.That(body.TryGetMechanismBehaviors(out List<LungBehavior> lungs));
|
||||||
Assert.That(lungs.Count, Is.EqualTo(1));
|
Assert.That(lungs.Count, Is.EqualTo(1));
|
||||||
Assert.That(human.TryGetComponent(out BloodstreamComponent bloodstream));
|
Assert.That(human.TryGetComponent(out BloodstreamComponent bloodstream));
|
||||||
@@ -167,7 +167,7 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
var coordinates = new EntityCoordinates(grid.GridEntityId, center);
|
var coordinates = new EntityCoordinates(grid.GridEntityId, center);
|
||||||
human = entityManager.SpawnEntity("HumanBodyAndBloodstreamDummy", coordinates);
|
human = entityManager.SpawnEntity("HumanBodyAndBloodstreamDummy", coordinates);
|
||||||
|
|
||||||
Assert.True(human.TryGetComponent(out IBody body));
|
Assert.True(human.TryGetComponent(out SharedBodyComponent body));
|
||||||
Assert.True(body.HasMechanismBehavior<LungBehavior>());
|
Assert.True(body.HasMechanismBehavior<LungBehavior>());
|
||||||
Assert.True(human.TryGetComponent(out metabolism));
|
Assert.True(human.TryGetComponent(out metabolism));
|
||||||
Assert.False(metabolism.Suffocating);
|
Assert.False(metabolism.Suffocating);
|
||||||
|
|||||||
@@ -59,42 +59,42 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
ResetRemoved();
|
ResetRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAddedToBody(IBody body)
|
protected override void OnAddedToBody(SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
base.OnAddedToBody(body);
|
base.OnAddedToBody(body);
|
||||||
|
|
||||||
WasAddedToBody = true;
|
WasAddedToBody = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAddedToPart(IBodyPart part)
|
protected override void OnAddedToPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
base.OnAddedToPart(part);
|
base.OnAddedToPart(part);
|
||||||
|
|
||||||
WasAddedToPart = true;
|
WasAddedToPart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAddedToPartInBody(IBody body, IBodyPart part)
|
protected override void OnAddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
base.OnAddedToPartInBody(body, part);
|
base.OnAddedToPartInBody(body, part);
|
||||||
|
|
||||||
WasAddedToPartInBody = true;
|
WasAddedToPartInBody = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRemovedFromBody(IBody old)
|
protected override void OnRemovedFromBody(SharedBodyComponent old)
|
||||||
{
|
{
|
||||||
base.OnRemovedFromBody(old);
|
base.OnRemovedFromBody(old);
|
||||||
|
|
||||||
WasRemovedFromBody = true;
|
WasRemovedFromBody = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRemovedFromPart(IBodyPart old)
|
protected override void OnRemovedFromPart(SharedBodyPartComponent old)
|
||||||
{
|
{
|
||||||
base.OnRemovedFromPart(old);
|
base.OnRemovedFromPart(old);
|
||||||
|
|
||||||
WasRemovedFromPart = true;
|
WasRemovedFromPart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRemovedFromPartInBody(IBody oldBody, IBodyPart oldPart)
|
protected override void OnRemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart)
|
||||||
{
|
{
|
||||||
base.OnRemovedFromPartInBody(oldBody, oldPart);
|
base.OnRemovedFromPartInBody(oldBody, oldPart);
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||||
var human = entityManager.SpawnEntity("HumanBodyDummy", new MapCoordinates(Vector2.Zero, mapId));
|
var human = entityManager.SpawnEntity("HumanBodyDummy", new MapCoordinates(Vector2.Zero, mapId));
|
||||||
|
|
||||||
Assert.That(human.TryGetComponent(out IBody? body));
|
Assert.That(human.TryGetComponent(out SharedBodyComponent? body));
|
||||||
Assert.NotNull(body);
|
Assert.NotNull(body);
|
||||||
|
|
||||||
var centerPart = body!.CenterPart;
|
var centerPart = body!.CenterPart;
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ namespace Content.IntegrationTests.Tests.Buckle
|
|||||||
IEntity human = null;
|
IEntity human = null;
|
||||||
BuckleComponent buckle = null;
|
BuckleComponent buckle = null;
|
||||||
HandsComponent hands = null;
|
HandsComponent hands = null;
|
||||||
IBody body = null;
|
SharedBodyComponent body = null;
|
||||||
|
|
||||||
await server.WaitIdleAsync();
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking
|
|||||||
// Test for components existing
|
// Test for components existing
|
||||||
Assert.True(human.TryGetComponent(out cuffed!), $"Human has no {nameof(CuffableComponent)}");
|
Assert.True(human.TryGetComponent(out cuffed!), $"Human has no {nameof(CuffableComponent)}");
|
||||||
Assert.True(human.TryGetComponent(out hands!), $"Human has no {nameof(HandsComponent)}");
|
Assert.True(human.TryGetComponent(out hands!), $"Human has no {nameof(HandsComponent)}");
|
||||||
Assert.True(human.TryGetComponent(out IBody _), $"Human has no {nameof(IBody)}");
|
Assert.True(human.TryGetComponent(out SharedBodyComponent _), $"Human has no {nameof(SharedBodyComponent)}");
|
||||||
Assert.True(cuffs.TryGetComponent(out HandcuffComponent _), $"Handcuff has no {nameof(HandcuffComponent)}");
|
Assert.True(cuffs.TryGetComponent(out HandcuffComponent _), $"Handcuff has no {nameof(HandcuffComponent)}");
|
||||||
Assert.True(secondCuffs.TryGetComponent(out HandcuffComponent _), $"Second handcuffs has no {nameof(HandcuffComponent)}");
|
Assert.True(secondCuffs.TryGetComponent(out HandcuffComponent _), $"Second handcuffs has no {nameof(HandcuffComponent)}");
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Content.Server.AI.WorldState.States.Mobs
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var entity in Visibility.GetEntitiesInRange(Owner.Transform.Coordinates, typeof(IBody), controller.VisionRadius))
|
foreach (var entity in Visibility.GetEntitiesInRange(Owner.Transform.Coordinates, typeof(SharedBodyComponent), controller.VisionRadius))
|
||||||
{
|
{
|
||||||
if (entity == Owner) continue;
|
if (entity == Owner) continue;
|
||||||
result.Add(entity);
|
result.Add(entity);
|
||||||
|
|||||||
@@ -11,42 +11,42 @@ namespace Content.Server.Body.Behavior
|
|||||||
{
|
{
|
||||||
public class BrainBehavior : MechanismBehavior
|
public class BrainBehavior : MechanismBehavior
|
||||||
{
|
{
|
||||||
protected override void OnAddedToBody(IBody body)
|
protected override void OnAddedToBody(SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
base.OnAddedToBody(body);
|
base.OnAddedToBody(body);
|
||||||
|
|
||||||
HandleMind(body.Owner, Owner);
|
HandleMind(body.Owner, Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAddedToPart(IBodyPart part)
|
protected override void OnAddedToPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
base.OnAddedToPart(part);
|
base.OnAddedToPart(part);
|
||||||
|
|
||||||
HandleMind(part.Owner, Owner);
|
HandleMind(part.Owner, Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAddedToPartInBody(IBody body, IBodyPart part)
|
protected override void OnAddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
base.OnAddedToPartInBody(body, part);
|
base.OnAddedToPartInBody(body, part);
|
||||||
|
|
||||||
HandleMind(body.Owner, Owner);
|
HandleMind(body.Owner, Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRemovedFromBody(IBody old)
|
protected override void OnRemovedFromBody(SharedBodyComponent old)
|
||||||
{
|
{
|
||||||
base.OnRemovedFromBody(old);
|
base.OnRemovedFromBody(old);
|
||||||
|
|
||||||
HandleMind(Part!.Owner, old.Owner);
|
HandleMind(Part!.Owner, old.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRemovedFromPart(IBodyPart old)
|
protected override void OnRemovedFromPart(SharedBodyPartComponent old)
|
||||||
{
|
{
|
||||||
base.OnRemovedFromPart(old);
|
base.OnRemovedFromPart(old);
|
||||||
|
|
||||||
HandleMind(Owner, old.Owner);
|
HandleMind(Owner, old.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRemovedFromPartInBody(IBody oldBody, IBodyPart oldPart)
|
protected override void OnRemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart)
|
||||||
{
|
{
|
||||||
base.OnRemovedFromPartInBody(oldBody, oldPart);
|
base.OnRemovedFromPartInBody(oldBody, oldPart);
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Content.Server.Body.Behavior
|
|||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAddedToBody(IBody body)
|
protected override void OnAddedToBody(SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
base.OnAddedToBody(body);
|
base.OnAddedToBody(body);
|
||||||
Inhale(CycleDelay);
|
Inhale(CycleDelay);
|
||||||
|
|||||||
@@ -8,22 +8,24 @@ using Robust.Shared.Utility;
|
|||||||
|
|
||||||
namespace Content.Server.Body.Behavior
|
namespace Content.Server.Body.Behavior
|
||||||
{
|
{
|
||||||
public abstract class MechanismBehavior : IMechanismBehavior
|
public abstract class MechanismBehavior : SharedMechanismBehavior
|
||||||
{
|
{
|
||||||
public IBody? Body => Part?.Body;
|
private SharedMechanismComponent _parent = default!;
|
||||||
|
|
||||||
public IBodyPart? Part => Parent.Part;
|
public override SharedBodyComponent? Body => Part?.Body;
|
||||||
|
|
||||||
public IMechanism Parent { get; private set; } = default!;
|
public override SharedBodyPartComponent? Part => Parent.Part;
|
||||||
|
|
||||||
public IEntity Owner => Parent.Owner;
|
public override SharedMechanismComponent Parent => _parent;
|
||||||
|
|
||||||
public virtual void Initialize(IMechanism parent)
|
public override IEntity Owner => Parent.Owner;
|
||||||
|
|
||||||
|
public override void Initialize(SharedMechanismComponent parent)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
_parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Startup()
|
public override void Startup()
|
||||||
{
|
{
|
||||||
if (Part == null)
|
if (Part == null)
|
||||||
{
|
{
|
||||||
@@ -40,7 +42,9 @@ namespace Content.Server.Body.Behavior
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddedToBody(IBody body)
|
public override void Update(float frameTime) { }
|
||||||
|
|
||||||
|
public override void AddedToBody(SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(Body);
|
DebugTools.AssertNotNull(Body);
|
||||||
DebugTools.AssertNotNull(body);
|
DebugTools.AssertNotNull(body);
|
||||||
@@ -48,7 +52,7 @@ namespace Content.Server.Body.Behavior
|
|||||||
OnAddedToBody(body);
|
OnAddedToBody(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddedToPart(IBodyPart part)
|
public override void AddedToPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(Part);
|
DebugTools.AssertNotNull(Part);
|
||||||
DebugTools.AssertNotNull(part);
|
DebugTools.AssertNotNull(part);
|
||||||
@@ -56,7 +60,7 @@ namespace Content.Server.Body.Behavior
|
|||||||
OnAddedToPart(part);
|
OnAddedToPart(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddedToPartInBody(IBody body, IBodyPart part)
|
public override void AddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(Body);
|
DebugTools.AssertNotNull(Body);
|
||||||
DebugTools.AssertNotNull(body);
|
DebugTools.AssertNotNull(body);
|
||||||
@@ -66,7 +70,7 @@ namespace Content.Server.Body.Behavior
|
|||||||
OnAddedToPartInBody(body, part);
|
OnAddedToPartInBody(body, part);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovedFromBody(IBody old)
|
public override void RemovedFromBody(SharedBodyComponent old)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNull(Body);
|
DebugTools.AssertNull(Body);
|
||||||
DebugTools.AssertNotNull(old);
|
DebugTools.AssertNotNull(old);
|
||||||
@@ -74,7 +78,7 @@ namespace Content.Server.Body.Behavior
|
|||||||
OnRemovedFromBody(old);
|
OnRemovedFromBody(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovedFromPart(IBodyPart old)
|
public override void RemovedFromPart(SharedBodyPartComponent old)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNull(Part);
|
DebugTools.AssertNull(Part);
|
||||||
DebugTools.AssertNotNull(old);
|
DebugTools.AssertNotNull(old);
|
||||||
@@ -82,7 +86,7 @@ namespace Content.Server.Body.Behavior
|
|||||||
OnRemovedFromPart(old);
|
OnRemovedFromPart(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovedFromPartInBody(IBody oldBody, IBodyPart oldPart)
|
public override void RemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNull(Body);
|
DebugTools.AssertNull(Body);
|
||||||
DebugTools.AssertNull(Part);
|
DebugTools.AssertNull(Part);
|
||||||
@@ -92,18 +96,16 @@ namespace Content.Server.Body.Behavior
|
|||||||
OnRemovedFromPartInBody(oldBody, oldPart);
|
OnRemovedFromPartInBody(oldBody, oldPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnAddedToBody(IBody body) { }
|
protected virtual void OnAddedToBody(SharedBodyComponent body) { }
|
||||||
|
|
||||||
protected virtual void OnAddedToPart(IBodyPart part) { }
|
protected virtual void OnAddedToPart(SharedBodyPartComponent part) { }
|
||||||
|
|
||||||
protected virtual void OnAddedToPartInBody(IBody body, IBodyPart part) { }
|
protected virtual void OnAddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part) { }
|
||||||
|
|
||||||
protected virtual void OnRemovedFromBody(IBody old) { }
|
protected virtual void OnRemovedFromBody(SharedBodyComponent old) { }
|
||||||
|
|
||||||
protected virtual void OnRemovedFromPart(IBodyPart old) { }
|
protected virtual void OnRemovedFromPart(SharedBodyPartComponent old) { }
|
||||||
|
|
||||||
protected virtual void OnRemovedFromPartInBody(IBody oldBody, IBodyPart oldPart) { }
|
protected virtual void OnRemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart) { }
|
||||||
|
|
||||||
public virtual void Update(float frameTime) { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Linq;
|
|
||||||
using Content.Shared.Body.Behavior;
|
|
||||||
using Content.Shared.Body.Components;
|
|
||||||
using Content.Shared.Body.Part;
|
|
||||||
|
|
||||||
namespace Content.Server.Body.Behavior
|
|
||||||
{
|
|
||||||
public static class MechanismExtensions
|
|
||||||
{
|
|
||||||
public static bool HasMechanismBehavior<T>(this IBody body) where T : IMechanismBehavior
|
|
||||||
{
|
|
||||||
return body.Parts.Any(p => p.Key.HasMechanismBehavior<T>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasMechanismBehavior<T>(this IBodyPart part) where T : IMechanismBehavior
|
|
||||||
{
|
|
||||||
return part.Mechanisms.Any(m => m.HasBehavior<T>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<IMechanismBehavior> GetMechanismBehaviors(this IBody body)
|
|
||||||
{
|
|
||||||
foreach (var (part, _) in body.Parts)
|
|
||||||
foreach (var mechanism in part.Mechanisms)
|
|
||||||
foreach (var behavior in mechanism.Behaviors.Values)
|
|
||||||
{
|
|
||||||
yield return behavior;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryGetMechanismBehaviors(this IBody body,
|
|
||||||
[NotNullWhen(true)] out List<IMechanismBehavior>? behaviors)
|
|
||||||
{
|
|
||||||
behaviors = body.GetMechanismBehaviors().ToList();
|
|
||||||
|
|
||||||
if (behaviors.Count == 0)
|
|
||||||
{
|
|
||||||
behaviors = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<T> GetMechanismBehaviors<T>(this IBody body) where T : class, IMechanismBehavior
|
|
||||||
{
|
|
||||||
foreach (var (part, _) in body.Parts)
|
|
||||||
foreach (var mechanism in part.Mechanisms)
|
|
||||||
foreach (var behavior in mechanism.Behaviors.Values)
|
|
||||||
{
|
|
||||||
if (behavior is T tBehavior)
|
|
||||||
{
|
|
||||||
yield return tBehavior;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryGetMechanismBehaviors<T>(this IBody entity, [NotNullWhen(true)] out List<T>? behaviors)
|
|
||||||
where T : class, IMechanismBehavior
|
|
||||||
{
|
|
||||||
behaviors = entity.GetMechanismBehaviors<T>().ToList();
|
|
||||||
|
|
||||||
if (behaviors.Count == 0)
|
|
||||||
{
|
|
||||||
behaviors = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,27 +21,26 @@ namespace Content.Server.Body
|
|||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(SharedBodyComponent))]
|
[ComponentReference(typeof(SharedBodyComponent))]
|
||||||
[ComponentReference(typeof(IBody))]
|
|
||||||
[ComponentReference(typeof(IGhostOnMove))]
|
[ComponentReference(typeof(IGhostOnMove))]
|
||||||
public class BodyComponent : SharedBodyComponent, IRelayMoveInput, IGhostOnMove
|
public class BodyComponent : SharedBodyComponent, IRelayMoveInput, IGhostOnMove
|
||||||
{
|
{
|
||||||
private Container _partContainer = default!;
|
private Container _partContainer = default!;
|
||||||
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
||||||
|
|
||||||
protected override bool CanAddPart(string slotId, IBodyPart part)
|
protected override bool CanAddPart(string slotId, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
return base.CanAddPart(slotId, part) &&
|
return base.CanAddPart(slotId, part) &&
|
||||||
_partContainer.CanInsert(part.Owner);
|
_partContainer.CanInsert(part.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAddPart(BodyPartSlot slot, IBodyPart part)
|
protected override void OnAddPart(BodyPartSlot slot, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
base.OnAddPart(slot, part);
|
base.OnAddPart(slot, part);
|
||||||
|
|
||||||
_partContainer.Insert(part.Owner);
|
_partContainer.Insert(part.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRemovePart(BodyPartSlot slot, IBodyPart part)
|
protected override void OnRemovePart(BodyPartSlot slot, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
base.OnRemovePart(slot, part);
|
base.OnRemovePart(slot, part);
|
||||||
|
|
||||||
@@ -64,9 +63,9 @@ namespace Content.Server.Body
|
|||||||
// a crash within the character preview menu in the lobby
|
// a crash within the character preview menu in the lobby
|
||||||
var entity = Owner.EntityManager.SpawnEntity(preset.PartIDs[slot.Id], Owner.Transform.MapPosition);
|
var entity = Owner.EntityManager.SpawnEntity(preset.PartIDs[slot.Id], Owner.Transform.MapPosition);
|
||||||
|
|
||||||
if (!entity.TryGetComponent(out IBodyPart? part))
|
if (!entity.TryGetComponent(out SharedBodyPartComponent? part))
|
||||||
{
|
{
|
||||||
Logger.Error($"Entity {slot.Id} does not have a {nameof(IBodyPart)} component.");
|
Logger.Error($"Entity {slot.Id} does not have a {nameof(SharedBodyPartComponent)} component.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ using Content.Shared.Damage;
|
|||||||
|
|
||||||
namespace Content.Server.Body
|
namespace Content.Server.Body
|
||||||
{
|
{
|
||||||
|
// TODO BODY: Remove and pretend it never existed
|
||||||
public interface IBodyHealthChangeParams
|
public interface IBodyHealthChangeParams
|
||||||
{
|
{
|
||||||
BodyPartType Part { get; }
|
BodyPartType Part { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO BODY: Remove and pretend it never existed
|
||||||
public class BodyDamageChangeParams : DamageChangeParams, IBodyHealthChangeParams
|
public class BodyDamageChangeParams : DamageChangeParams, IBodyHealthChangeParams
|
||||||
{
|
{
|
||||||
public BodyDamageChangeParams(BodyPartType part)
|
public BodyDamageChangeParams(BodyPartType part)
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ namespace Content.Server.Body.Commands
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entity.TryGetComponent(out IBody? body))
|
if (!entity.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
var random = IoCManager.Resolve<IRobustRandom>();
|
var random = IoCManager.Resolve<IRobustRandom>();
|
||||||
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
||||||
@@ -131,9 +131,9 @@ namespace Content.Server.Body.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hand.TryGetComponent(out IBodyPart? part))
|
if (!hand.TryGetComponent(out SharedBodyPartComponent? part))
|
||||||
{
|
{
|
||||||
shell.WriteLine($"Hand entity {hand} does not have a {nameof(IBodyPart)} component.");
|
shell.WriteLine($"Hand entity {hand} does not have a {nameof(SharedBodyPartComponent)} component.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,9 +76,9 @@ namespace Content.Server.Body.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entity.TryGetComponent(out IBody? body))
|
if (!entity.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
shell.WriteLine($"Entity {entity.Name} with uid {entity.Uid} does not have a {nameof(IBody)} component.");
|
shell.WriteLine($"Entity {entity.Name} with uid {entity.Uid} does not have a {nameof(SharedBodyComponent)} component.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,9 +88,9 @@ namespace Content.Server.Body.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!partEntity.TryGetComponent(out IBodyPart? part))
|
if (!partEntity.TryGetComponent(out SharedBodyPartComponent? part))
|
||||||
{
|
{
|
||||||
shell.WriteLine($"Entity {partEntity.Name} with uid {args[0]} does not have a {nameof(IBodyPart)} component.");
|
shell.WriteLine($"Entity {partEntity.Name} with uid {args[0]} does not have a {nameof(SharedBodyPartComponent)} component.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Content.Server.Body.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!player.AttachedEntity.TryGetComponent(out IBody? body))
|
if (!player.AttachedEntity.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
var random = IoCManager.Resolve<IRobustRandom>();
|
var random = IoCManager.Resolve<IRobustRandom>();
|
||||||
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace Content.Server.Body.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!player.AttachedEntity.TryGetComponent(out IBody? body))
|
if (!player.AttachedEntity.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
var random = IoCManager.Resolve<IRobustRandom>();
|
var random = IoCManager.Resolve<IRobustRandom>();
|
||||||
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ namespace Content.Server.Body.Mechanism
|
|||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(SharedMechanismComponent))]
|
[ComponentReference(typeof(SharedMechanismComponent))]
|
||||||
[ComponentReference(typeof(IMechanism))]
|
|
||||||
public class MechanismComponent : SharedMechanismComponent, IAfterInteract
|
public class MechanismComponent : SharedMechanismComponent, IAfterInteract
|
||||||
{
|
{
|
||||||
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SurgeryUIKey.Key);
|
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SurgeryUIKey.Key);
|
||||||
@@ -47,11 +46,11 @@ namespace Content.Server.Body.Mechanism
|
|||||||
PerformerCache = null;
|
PerformerCache = null;
|
||||||
BodyCache = null;
|
BodyCache = null;
|
||||||
|
|
||||||
if (eventArgs.Target.TryGetComponent(out IBody? body))
|
if (eventArgs.Target.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
SendBodyPartListToUser(eventArgs, body);
|
SendBodyPartListToUser(eventArgs, body);
|
||||||
}
|
}
|
||||||
else if (eventArgs.Target.TryGetComponent<IBodyPart>(out var part))
|
else if (eventArgs.Target.TryGetComponent<SharedBodyPartComponent>(out var part))
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(part);
|
DebugTools.AssertNotNull(part);
|
||||||
|
|
||||||
@@ -64,7 +63,7 @@ namespace Content.Server.Body.Mechanism
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendBodyPartListToUser(AfterInteractEventArgs eventArgs, IBody body)
|
private void SendBodyPartListToUser(AfterInteractEventArgs eventArgs, SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
// Create dictionary to send to client (text to be shown : data sent back if selected)
|
// Create dictionary to send to client (text to be shown : data sent back if selected)
|
||||||
var toSend = new Dictionary<string, int>();
|
var toSend = new Dictionary<string, int>();
|
||||||
@@ -120,7 +119,7 @@ namespace Content.Server.Body.Mechanism
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var target = (IBodyPart) targetObject;
|
var target = (SharedBodyPartComponent) targetObject;
|
||||||
var message = target.TryAddMechanism(this)
|
var message = target.TryAddMechanism(this)
|
||||||
? Loc.GetString("You jam {0:theName} inside {1:them}.", Owner, PerformerCache)
|
? Loc.GetString("You jam {0:theName} inside {1:them}.", Owner, PerformerCache)
|
||||||
: Loc.GetString("You can't fit it in!");
|
: Loc.GetString("You can't fit it in!");
|
||||||
|
|||||||
@@ -25,31 +25,30 @@ namespace Content.Server.Body.Part
|
|||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(SharedBodyPartComponent))]
|
[ComponentReference(typeof(SharedBodyPartComponent))]
|
||||||
[ComponentReference(typeof(IBodyPart))]
|
|
||||||
public class BodyPartComponent : SharedBodyPartComponent, IAfterInteract
|
public class BodyPartComponent : SharedBodyPartComponent, IAfterInteract
|
||||||
{
|
{
|
||||||
private readonly Dictionary<int, object> _optionsCache = new();
|
private readonly Dictionary<int, object> _optionsCache = new();
|
||||||
private IBody? _owningBodyCache;
|
private SharedBodyComponent? _owningBodyCache;
|
||||||
private int _idHash;
|
private int _idHash;
|
||||||
private IEntity? _surgeonCache;
|
private IEntity? _surgeonCache;
|
||||||
private Container _mechanismContainer = default!;
|
private Container _mechanismContainer = default!;
|
||||||
|
|
||||||
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SurgeryUIKey.Key);
|
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SurgeryUIKey.Key);
|
||||||
|
|
||||||
public override bool CanAddMechanism(IMechanism mechanism)
|
public override bool CanAddMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
return base.CanAddMechanism(mechanism) &&
|
return base.CanAddMechanism(mechanism) &&
|
||||||
_mechanismContainer.CanInsert(mechanism.Owner);
|
_mechanismContainer.CanInsert(mechanism.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAddMechanism(IMechanism mechanism)
|
protected override void OnAddMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
base.OnAddMechanism(mechanism);
|
base.OnAddMechanism(mechanism);
|
||||||
|
|
||||||
_mechanismContainer.Insert(mechanism.Owner);
|
_mechanismContainer.Insert(mechanism.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRemoveMechanism(IMechanism mechanism)
|
protected override void OnRemoveMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
base.OnRemoveMechanism(mechanism);
|
base.OnRemoveMechanism(mechanism);
|
||||||
|
|
||||||
@@ -70,9 +69,9 @@ namespace Content.Server.Body.Part
|
|||||||
{
|
{
|
||||||
var entity = Owner.EntityManager.SpawnEntity(mechanismId, Owner.Transform.MapPosition);
|
var entity = Owner.EntityManager.SpawnEntity(mechanismId, Owner.Transform.MapPosition);
|
||||||
|
|
||||||
if (!entity.TryGetComponent(out IMechanism? mechanism))
|
if (!entity.TryGetComponent(out SharedMechanismComponent? mechanism))
|
||||||
{
|
{
|
||||||
Logger.Error($"Entity {mechanismId} does not have a {nameof(IMechanism)} component.");
|
Logger.Error($"Entity {mechanismId} does not have a {nameof(SharedMechanismComponent)} component.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +107,7 @@ namespace Content.Server.Body.Part
|
|||||||
_surgeonCache = null;
|
_surgeonCache = null;
|
||||||
_owningBodyCache = null;
|
_owningBodyCache = null;
|
||||||
|
|
||||||
if (eventArgs.Target.TryGetComponent(out IBody? body))
|
if (eventArgs.Target.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
SendSlots(eventArgs, body);
|
SendSlots(eventArgs, body);
|
||||||
}
|
}
|
||||||
@@ -116,7 +115,7 @@ namespace Content.Server.Body.Part
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendSlots(AfterInteractEventArgs eventArgs, IBody body)
|
private void SendSlots(AfterInteractEventArgs eventArgs, SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
// Create dictionary to send to client (text to be shown : data sent back if selected)
|
// Create dictionary to send to client (text to be shown : data sent back if selected)
|
||||||
var toSend = new Dictionary<string, int>();
|
var toSend = new Dictionary<string, int>();
|
||||||
@@ -246,7 +245,7 @@ namespace Content.Server.Body.Part
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.TryGetComponent(out IBody? body))
|
if (!user.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -262,7 +261,7 @@ namespace Content.Server.Body.Part
|
|||||||
|
|
||||||
protected override void Activate(IEntity user, BodyPartComponent component)
|
protected override void Activate(IEntity user, BodyPartComponent component)
|
||||||
{
|
{
|
||||||
if (!user.TryGetComponent(out IBody? body))
|
if (!user.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Content.Server.Body.Scanner
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.AttachedEntity.TryGetComponent(out IBody? body))
|
if (session.AttachedEntity.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
var state = InterfaceState(body);
|
var state = InterfaceState(body);
|
||||||
UserInterface?.SetState(state);
|
UserInterface?.SetState(state);
|
||||||
@@ -56,7 +56,7 @@ namespace Content.Server.Body.Scanner
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copy BodyTemplate and BodyPart data into a common data class that the client can read.
|
/// Copy BodyTemplate and BodyPart data into a common data class that the client can read.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private BodyScannerUIState InterfaceState(IBody body)
|
private BodyScannerUIState InterfaceState(SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
return new(body.Owner.Uid);
|
return new(body.Owner.Uid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Content.Server.Body.Surgery
|
|||||||
{
|
{
|
||||||
public override string Name => "BiologicalSurgeryData";
|
public override string Name => "BiologicalSurgeryData";
|
||||||
|
|
||||||
private readonly HashSet<IMechanism> _disconnectedOrgans = new();
|
private readonly HashSet<SharedMechanismComponent> _disconnectedOrgans = new();
|
||||||
|
|
||||||
private bool SkinOpened { get; set; }
|
private bool SkinOpened { get; set; }
|
||||||
|
|
||||||
@@ -33,11 +33,11 @@ namespace Content.Server.Body.Surgery
|
|||||||
|
|
||||||
private bool VesselsClamped { get; set; }
|
private bool VesselsClamped { get; set; }
|
||||||
|
|
||||||
public IBodyPart? Parent => Owner.GetComponentOrNull<IBodyPart>();
|
public SharedBodyPartComponent? Parent => Owner.GetComponentOrNull<SharedBodyPartComponent>();
|
||||||
|
|
||||||
public BodyPartType? ParentType => Parent?.PartType;
|
public BodyPartType? ParentType => Parent?.PartType;
|
||||||
|
|
||||||
private void AddDisconnectedOrgan(IMechanism mechanism)
|
private void AddDisconnectedOrgan(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
if (_disconnectedOrgans.Add(mechanism))
|
if (_disconnectedOrgans.Add(mechanism))
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ namespace Content.Server.Body.Surgery
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveDisconnectedOrgan(IMechanism mechanism)
|
private void RemoveDisconnectedOrgan(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
if (_disconnectedOrgans.Remove(mechanism))
|
if (_disconnectedOrgans.Remove(mechanism))
|
||||||
{
|
{
|
||||||
@@ -117,7 +117,7 @@ namespace Content.Server.Body.Surgery
|
|||||||
return toReturn.ToString();
|
return toReturn.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanAddMechanism(IMechanism mechanism)
|
public bool CanAddMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
return Parent != null &&
|
return Parent != null &&
|
||||||
SkinOpened &&
|
SkinOpened &&
|
||||||
@@ -125,7 +125,7 @@ namespace Content.Server.Body.Surgery
|
|||||||
SkinRetracted;
|
SkinRetracted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanAttachBodyPart(IBodyPart part)
|
public bool CanAttachBodyPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
return Parent != null;
|
return Parent != null;
|
||||||
// TODO BODY if a part is disconnected, you should have to do some surgery to allow another body part to be attached.
|
// TODO BODY if a part is disconnected, you should have to do some surgery to allow another body part to be attached.
|
||||||
@@ -276,7 +276,7 @@ namespace Content.Server.Body.Surgery
|
|||||||
if (Parent == null) return;
|
if (Parent == null) return;
|
||||||
if (Parent.Mechanisms.Count <= 0) return;
|
if (Parent.Mechanisms.Count <= 0) return;
|
||||||
|
|
||||||
var toSend = new List<IMechanism>();
|
var toSend = new List<SharedMechanismComponent>();
|
||||||
foreach (var mechanism in Parent.Mechanisms)
|
foreach (var mechanism in Parent.Mechanisms)
|
||||||
{
|
{
|
||||||
if (!_disconnectedOrgans.Contains(mechanism))
|
if (!_disconnectedOrgans.Contains(mechanism))
|
||||||
@@ -291,7 +291,7 @@ namespace Content.Server.Body.Surgery
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void LoosenOrganSurgeryCallback(IMechanism? target, IBodyPartContainer container, ISurgeon surgeon,
|
private async void LoosenOrganSurgeryCallback(SharedMechanismComponent? target, IBodyPartContainer container, ISurgeon surgeon,
|
||||||
IEntity performer)
|
IEntity performer)
|
||||||
{
|
{
|
||||||
if (Parent == null || target == null || !Parent.Mechanisms.Contains(target))
|
if (Parent == null || target == null || !Parent.Mechanisms.Contains(target))
|
||||||
@@ -332,7 +332,7 @@ namespace Content.Server.Body.Surgery
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RemoveOrganSurgeryCallback(IMechanism? target, IBodyPartContainer container, ISurgeon surgeon,
|
private async void RemoveOrganSurgeryCallback(SharedMechanismComponent? target, IBodyPartContainer container, ISurgeon surgeon,
|
||||||
IEntity performer)
|
IEntity performer)
|
||||||
{
|
{
|
||||||
if (Parent == null || target == null || !Parent.Mechanisms.Contains(target))
|
if (Parent == null || target == null || !Parent.Mechanisms.Contains(target))
|
||||||
@@ -359,7 +359,7 @@ namespace Content.Server.Body.Surgery
|
|||||||
private async void RemoveBodyPartSurgery(IBodyPartContainer container, ISurgeon surgeon, IEntity performer)
|
private async void RemoveBodyPartSurgery(IBodyPartContainer container, ISurgeon surgeon, IEntity performer)
|
||||||
{
|
{
|
||||||
if (Parent == null) return;
|
if (Parent == null) return;
|
||||||
if (container is not IBody body) return;
|
if (container is not SharedBodyComponent body) return;
|
||||||
|
|
||||||
performer.PopupMessage(Loc.GetString("Sawing off the limb!"));
|
performer.PopupMessage(Loc.GetString("Sawing off the limb!"));
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace Content.Server.Body.Surgery.Components
|
|||||||
|
|
||||||
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SurgeryUIKey.Key);
|
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SurgeryUIKey.Key);
|
||||||
|
|
||||||
public IBody? BodyCache { get; private set; }
|
public SharedBodyComponent? BodyCache { get; private set; }
|
||||||
|
|
||||||
public IEntity? PerformerCache { get; private set; }
|
public IEntity? PerformerCache { get; private set; }
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ namespace Content.Server.Body.Surgery.Components
|
|||||||
CloseAllSurgeryUIs();
|
CloseAllSurgeryUIs();
|
||||||
|
|
||||||
// Attempt surgery on a body by sending a list of operable parts for the client to choose from
|
// Attempt surgery on a body by sending a list of operable parts for the client to choose from
|
||||||
if (eventArgs.Target.TryGetComponent(out IBody? body))
|
if (eventArgs.Target.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
// Create dictionary to send to client (text to be shown : data sent back if selected)
|
// Create dictionary to send to client (text to be shown : data sent back if selected)
|
||||||
var toSend = new Dictionary<string, int>();
|
var toSend = new Dictionary<string, int>();
|
||||||
@@ -93,7 +93,7 @@ namespace Content.Server.Body.Surgery.Components
|
|||||||
NotUsefulPopup();
|
NotUsefulPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eventArgs.Target.TryGetComponent<IBodyPart>(out var part))
|
else if (eventArgs.Target.TryGetComponent<SharedBodyPartComponent>(out var part))
|
||||||
{
|
{
|
||||||
// Attempt surgery on a DroppedBodyPart - there's only one possible target so no need for selection UI
|
// Attempt surgery on a DroppedBodyPart - there's only one possible target so no need for selection UI
|
||||||
PerformerCache = eventArgs.User;
|
PerformerCache = eventArgs.User;
|
||||||
@@ -113,7 +113,7 @@ namespace Content.Server.Body.Surgery.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Log error if the surgery fails somehow.
|
// Log error if the surgery fails somehow.
|
||||||
Logger.Debug($"Error when trying to perform surgery on ${nameof(IBodyPart)} {eventArgs.User.Name}");
|
Logger.Debug($"Error when trying to perform surgery on ${nameof(SharedBodyPartComponent)} {eventArgs.User.Name}");
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ namespace Content.Server.Body.Surgery.Components
|
|||||||
|
|
||||||
public float BaseOperationTime { get => _baseOperateTime; set => _baseOperateTime = value; }
|
public float BaseOperationTime { get => _baseOperateTime; set => _baseOperateTime = value; }
|
||||||
|
|
||||||
public void RequestMechanism(IEnumerable<IMechanism> options, ISurgeon.MechanismRequestCallback callback)
|
public void RequestMechanism(IEnumerable<SharedMechanismComponent> options, ISurgeon.MechanismRequestCallback callback)
|
||||||
{
|
{
|
||||||
var toSend = new Dictionary<string, int>();
|
var toSend = new Dictionary<string, int>();
|
||||||
foreach (var mechanism in options)
|
foreach (var mechanism in options)
|
||||||
@@ -211,7 +211,7 @@ namespace Content.Server.Body.Surgery.Components
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called after the client chooses from a list of possible
|
/// Called after the client chooses from a list of possible
|
||||||
/// <see cref="IBodyPart"/> that can be operated on.
|
/// <see cref="SharedBodyPartComponent"/> that can be operated on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void HandleReceiveBodyPart(int key)
|
private void HandleReceiveBodyPart(int key)
|
||||||
{
|
{
|
||||||
@@ -230,7 +230,7 @@ namespace Content.Server.Body.Surgery.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var target = (IBodyPart) targetObject!;
|
var target = (SharedBodyPartComponent) targetObject!;
|
||||||
|
|
||||||
// TODO BODY Reconsider
|
// TODO BODY Reconsider
|
||||||
if (!target.AttemptSurgery(_surgeryType, BodyCache, this, PerformerCache))
|
if (!target.AttemptSurgery(_surgeryType, BodyCache, this, PerformerCache))
|
||||||
@@ -241,7 +241,7 @@ namespace Content.Server.Body.Surgery.Components
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called after the client chooses from a list of possible
|
/// Called after the client chooses from a list of possible
|
||||||
/// <see cref="IMechanism"/> to choose from.
|
/// <see cref="SharedMechanismComponent"/> to choose from.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void HandleReceiveMechanism(int key)
|
private void HandleReceiveMechanism(int key)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Content.Server.CharacterAppearance.Components
|
|||||||
{
|
{
|
||||||
base.Appearance = value;
|
base.Appearance = value;
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out IBody? body))
|
if (Owner.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
foreach (var (part, _) in body.Parts)
|
foreach (var (part, _) in body.Parts)
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ namespace Content.Server.CharacterAppearance.Components
|
|||||||
{
|
{
|
||||||
base.Startup();
|
base.Startup();
|
||||||
|
|
||||||
if (Appearance != null! && Owner.TryGetComponent(out IBody? body))
|
if (Appearance != null! && Owner.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
foreach (var (part, _) in body.Parts)
|
foreach (var (part, _) in body.Parts)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace Content.Server.Chemistry.Components
|
|||||||
|
|
||||||
var trueTarget = target ?? user;
|
var trueTarget = target ?? user;
|
||||||
|
|
||||||
if (!trueTarget.TryGetComponent(out IBody? body) ||
|
if (!trueTarget.TryGetComponent(out SharedBodyComponent? body) ||
|
||||||
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace Content.Server.Climbing.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!user.HasComponent<ClimbingComponent>() ||
|
if (!user.HasComponent<ClimbingComponent>() ||
|
||||||
!user.TryGetComponent(out IBody? body))
|
!user.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
reason = Loc.GetString("comp-climbable-cant-climb");
|
reason = Loc.GetString("comp-climbable-cant-climb");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Content.Server.Destructible.Thresholds.Behaviors
|
|||||||
|
|
||||||
public void Execute(IEntity owner, DestructibleSystem system)
|
public void Execute(IEntity owner, DestructibleSystem system)
|
||||||
{
|
{
|
||||||
if (owner.TryGetComponent(out IBody? body))
|
if (owner.TryGetComponent(out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
body.Gib(_recursive);
|
body.Gib(_recursive);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ namespace Content.Server.Disposal.Mailing
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!entity.HasComponent<ItemComponent>() &&
|
if (!entity.HasComponent<ItemComponent>() &&
|
||||||
!entity.HasComponent<IBody>())
|
!entity.HasComponent<SharedBodyComponent>())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ namespace Content.Server.Disposal.Unit.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
return entity.HasComponent<ItemComponent>() ||
|
return entity.HasComponent<ItemComponent>() ||
|
||||||
entity.HasComponent<IBody>();
|
entity.HasComponent<SharedBodyComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryInsert(IEntity entity)
|
public bool TryInsert(IEntity entity)
|
||||||
|
|||||||
@@ -470,7 +470,7 @@ namespace Content.Server.Kitchen.Components
|
|||||||
{
|
{
|
||||||
var headCount = 0;
|
var headCount = 0;
|
||||||
|
|
||||||
if (victim.TryGetComponent<IBody>(out var body))
|
if (victim.TryGetComponent<SharedBodyComponent>(out var body))
|
||||||
{
|
{
|
||||||
var headSlots = body.GetSlotsOfType(BodyPartType.Head);
|
var headSlots = body.GetSlotsOfType(BodyPartType.Head);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Content.Server.Metabolism
|
|||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class MetabolismComponent : Component
|
public class MetabolismComponent : Component
|
||||||
{
|
{
|
||||||
[ComponentDependency] private readonly IBody? _body = default!;
|
[ComponentDependency] private readonly SharedBodyComponent? _body = default!;
|
||||||
|
|
||||||
public override string Name => "Metabolism";
|
public override string Name => "Metabolism";
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace Content.Server.Morgue.Components
|
|||||||
|
|
||||||
protected override bool AddToContents(IEntity entity)
|
protected override bool AddToContents(IEntity entity)
|
||||||
{
|
{
|
||||||
if (entity.HasComponent<IBody>() && !EntitySystem.Get<StandingStateSystem>().IsDown(entity)) return false;
|
if (entity.HasComponent<SharedBodyComponent>() && !EntitySystem.Get<StandingStateSystem>().IsDown(entity)) return false;
|
||||||
return base.AddToContents(entity);
|
return base.AddToContents(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace Content.Server.Morgue.Components
|
|||||||
|
|
||||||
protected override bool AddToContents(IEntity entity)
|
protected override bool AddToContents(IEntity entity)
|
||||||
{
|
{
|
||||||
if (entity.HasComponent<IBody>() && !EntitySystem.Get<StandingStateSystem>().IsDown(entity)) return false;
|
if (entity.HasComponent<SharedBodyComponent>() && !EntitySystem.Get<StandingStateSystem>().IsDown(entity)) return false;
|
||||||
return base.AddToContents(entity);
|
return base.AddToContents(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ namespace Content.Server.Morgue.Components
|
|||||||
foreach (var entity in Contents.ContainedEntities)
|
foreach (var entity in Contents.ContainedEntities)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if (!hasMob && entity.HasComponent<IBody>()) hasMob = true;
|
if (!hasMob && entity.HasComponent<SharedBodyComponent>()) hasMob = true;
|
||||||
if (!hasSoul && entity.TryGetComponent<ActorComponent>(out var actor) && actor.PlayerSession != null) hasSoul = true;
|
if (!hasSoul && entity.TryGetComponent<ActorComponent>(out var actor) && actor.PlayerSession != null) hasSoul = true;
|
||||||
}
|
}
|
||||||
Appearance?.SetData(MorgueVisuals.HasContents, count > 0);
|
Appearance?.SetData(MorgueVisuals.HasContents, count > 0);
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ namespace Content.Server.Nutrition.Components
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target.TryGetComponent(out IBody? body) ||
|
if (!target.TryGetComponent(out SharedBodyComponent? body) ||
|
||||||
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
||||||
{
|
{
|
||||||
target.PopupMessage(Loc.GetString("You can't drink {0:theName}!", Owner));
|
target.PopupMessage(Loc.GetString("You can't drink {0:theName}!", Owner));
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ namespace Content.Server.Nutrition.Components
|
|||||||
|
|
||||||
var trueTarget = target ?? user;
|
var trueTarget = target ?? user;
|
||||||
|
|
||||||
if (!trueTarget.TryGetComponent(out IBody? body) ||
|
if (!trueTarget.TryGetComponent(out SharedBodyComponent? body) ||
|
||||||
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace Content.Server.Recycling.Components
|
|||||||
private bool CanGib(IEntity entity)
|
private bool CanGib(IEntity entity)
|
||||||
{
|
{
|
||||||
// We suppose this entity has a Recyclable component.
|
// We suppose this entity has a Recyclable component.
|
||||||
return entity.HasComponent<IBody>() && !_safe && Powered;
|
return entity.HasComponent<SharedBodyComponent>() && !_safe && Powered;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Recycle(IEntity entity)
|
private void Recycle(IEntity entity)
|
||||||
@@ -87,7 +87,7 @@ namespace Content.Server.Recycling.Components
|
|||||||
// Mobs are a special case!
|
// Mobs are a special case!
|
||||||
if (CanGib(entity))
|
if (CanGib(entity))
|
||||||
{
|
{
|
||||||
entity.GetComponent<IBody>().Gib(true);
|
entity.GetComponent<SharedBodyComponent>().Gib(true);
|
||||||
Bloodstain();
|
Bloodstain();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ namespace Content.Server.Recycling.Components
|
|||||||
|
|
||||||
victim.PopupMessageOtherClients(Loc.GetString("{0:theName} tries to recycle {0:themself}!", victim));
|
victim.PopupMessageOtherClients(Loc.GetString("{0:theName} tries to recycle {0:themself}!", victim));
|
||||||
|
|
||||||
if (victim.TryGetComponent<IBody>(out var body))
|
if (victim.TryGetComponent<SharedBodyComponent>(out var body))
|
||||||
{
|
{
|
||||||
body.Gib(true);
|
body.Gib(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ namespace Content.Server.Storage.Components
|
|||||||
|
|
||||||
// only items that can be stored in an inventory, or a mob, can be eaten by a locker
|
// only items that can be stored in an inventory, or a mob, can be eaten by a locker
|
||||||
if (!entity.HasComponent<SharedItemComponent>() &&
|
if (!entity.HasComponent<SharedItemComponent>() &&
|
||||||
!entity.HasComponent<IBody>())
|
!entity.HasComponent<SharedBodyComponent>())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!AddToContents(entity))
|
if (!AddToContents(entity))
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ namespace Content.Server.Toilet
|
|||||||
SuicideKind ISuicideAct.Suicide(IEntity victim, IChatManager chat)
|
SuicideKind ISuicideAct.Suicide(IEntity victim, IChatManager chat)
|
||||||
{
|
{
|
||||||
// check that victim even have head
|
// check that victim even have head
|
||||||
if (victim.TryGetComponent<IBody>(out var body) &&
|
if (victim.TryGetComponent<SharedBodyComponent>(out var body) &&
|
||||||
body.HasPartOfType(BodyPartType.Head))
|
body.HasPartOfType(BodyPartType.Head))
|
||||||
{
|
{
|
||||||
var othersMessage = Loc.GetString("{0:theName} sticks their head into {1:theName} and flushes it!", victim, Owner);
|
var othersMessage = Loc.GetString("{0:theName} sticks their head into {1:theName} and flushes it!", victim, Owner);
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using Content.Shared.Body.Components;
|
|
||||||
using Content.Shared.Body.Mechanism;
|
|
||||||
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 <see cref="IMechanism"/> when added to it.
|
|
||||||
/// </summary>
|
|
||||||
[ImplicitDataDefinitionForInheritors]
|
|
||||||
public interface IMechanismBehavior
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The body that owns the <see cref="IBodyPart"/> in which the
|
|
||||||
/// <see cref="IMechanism"/> that owns this
|
|
||||||
/// <see cref="IMechanismBehavior"/> is in.
|
|
||||||
/// </summary>
|
|
||||||
IBody? Body { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The part in which the <see cref="IMechanism"/> that owns this
|
|
||||||
/// <see cref="IMechanismBehavior"/> is in.
|
|
||||||
/// </summary>
|
|
||||||
IBodyPart? Part { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Upward reference to the parent <see cref="IMechanism"/> that this
|
|
||||||
/// behavior is attached to.
|
|
||||||
/// </summary>
|
|
||||||
IMechanism 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="IBody.Owner"/>.
|
|
||||||
/// </summary>
|
|
||||||
IEntity Owner { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when this <see cref="IMechanismBehavior"/> is added to a
|
|
||||||
/// <see cref="IMechanism"/>, 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 <see cref="IMechanismBehavior"/>.
|
|
||||||
/// </param>
|
|
||||||
void Initialize(IMechanism parent);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when this <see cref="IMechanismBehavior"/> is added to a
|
|
||||||
/// <see cref="IMechanism"/>, during <see cref="IComponent.Startup"/>.
|
|
||||||
/// If it is added after component startup, it is called immediately.
|
|
||||||
/// </summary>
|
|
||||||
void Startup();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Runs an update cycle on this <see cref="IMechanismBehavior"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="frameTime">
|
|
||||||
/// The amount of seconds that passed since the last update.
|
|
||||||
/// </param>
|
|
||||||
void Update(float frameTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the containing <see cref="IBodyPart"/> is attached to a
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// 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 <see cref="IMechanism"/> was added to.
|
|
||||||
/// </param>
|
|
||||||
void AddedToBody(IBody body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IMechanism"/> is
|
|
||||||
/// added into a <see cref="IBodyPart"/> that is not attached to a
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// 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 <see cref="IMechanism"/> was added to.
|
|
||||||
/// </param>
|
|
||||||
void AddedToPart(IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IMechanism"/> is added to a
|
|
||||||
/// <see cref="IBodyPart"/> that is attached to a <see cref="IBody"/>.
|
|
||||||
/// 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 <see cref="IMechanism"/> was added to.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="part">
|
|
||||||
/// The part that the containing <see cref="IMechanism"/> was added to.
|
|
||||||
/// </param>
|
|
||||||
void AddedToPartInBody(IBody body, IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IBodyPart"/> is removed from a
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// 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 <see cref="IMechanism"/> was removed from.
|
|
||||||
/// </param>
|
|
||||||
void RemovedFromBody(IBody old);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IMechanism"/> is
|
|
||||||
/// removed from a <see cref="IBodyPart"/> that is not attached to a
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// 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 <see cref="IMechanism"/> was removed from.
|
|
||||||
/// </param>
|
|
||||||
void RemovedFromPart(IBodyPart old);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IMechanism"/> is removed from a
|
|
||||||
/// <see cref="IBodyPart"/> that is attached to a <see cref="IBody"/>.
|
|
||||||
/// 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 <see cref="IMechanism"/> was removed from.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="oldPart">
|
|
||||||
/// The part that the containing <see cref="IMechanism"/> was removed from.
|
|
||||||
/// </param>
|
|
||||||
void RemovedFromPartInBody(IBody oldBody, IBodyPart oldPart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
119
Content.Shared/Body/Behavior/SharedMechanismBehavior.cs
Normal file
119
Content.Shared/Body/Behavior/SharedMechanismBehavior.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#nullable enable
|
||||||
|
using Content.Shared.Body.Components;
|
||||||
|
using Content.Shared.Body.Mechanism;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,256 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using Content.Shared.Body.Part;
|
|
||||||
using Content.Shared.Body.Part.Property;
|
|
||||||
using Content.Shared.Body.Preset;
|
|
||||||
using Content.Shared.Body.Slot;
|
|
||||||
using Content.Shared.Body.Template;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Shared.Body.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Component representing a collection of <see cref="IBodyPart"/>s
|
|
||||||
/// attached to each other.
|
|
||||||
/// </summary>
|
|
||||||
public interface IBody : IComponent, IBodyPartContainer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="BodyTemplatePrototype"/> used to create this
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// </summary>
|
|
||||||
public BodyTemplatePrototype? Template { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="BodyPresetPrototype"/> used to create this
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// </summary>
|
|
||||||
public BodyPresetPrototype? Preset { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An enumeration of the slots that make up this body, regardless
|
|
||||||
/// of if they contain a part or not.
|
|
||||||
/// </summary>
|
|
||||||
IEnumerable<BodyPartSlot> Slots { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An enumeration of the parts on this body paired with the slots
|
|
||||||
/// that they are in.
|
|
||||||
/// </summary>
|
|
||||||
IEnumerable<KeyValuePair<IBodyPart, BodyPartSlot>> Parts { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An enumeration of the slots on this body without a part in them.
|
|
||||||
/// </summary>
|
|
||||||
IEnumerable<BodyPartSlot> EmptySlots { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the central <see cref="BodyPartSlot"/>, if any,
|
|
||||||
/// of this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// The central <see cref="BodyPartSlot"/> if one exists,
|
|
||||||
/// null otherwise.
|
|
||||||
/// </returns>
|
|
||||||
BodyPartSlot? CenterSlot { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the central <see cref="IBodyPart"/>, if any,
|
|
||||||
/// of this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// The central <see cref="IBodyPart"/> if one exists,
|
|
||||||
/// null otherwise.
|
|
||||||
/// </returns>
|
|
||||||
IBodyPart? CenterPart { get; }
|
|
||||||
|
|
||||||
// TODO BODY Sensible templates
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to add a part to the given slot.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="slotId">The slot to add this part to.</param>
|
|
||||||
/// <param name="part">The part to add.</param>
|
|
||||||
/// <param name="checkSlotExists">
|
|
||||||
/// Whether to check if the slot exists, or create one otherwise.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if the part was added, false otherwise even if it was
|
|
||||||
/// already added.
|
|
||||||
/// </returns>
|
|
||||||
bool TryAddPart(string slotId, IBodyPart part);
|
|
||||||
|
|
||||||
void SetPart(string slotId, IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if there is a <see cref="IBodyPart"/> in the given slot.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="slotId">The slot to look in.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if there is a part in the given <see cref="slotId"/>,
|
|
||||||
/// false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
bool HasPart(string slotId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if this <see cref="IBody"/> contains the given <see cref="part"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">The part to look for.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if the given <see cref="part"/> is attached to the body,
|
|
||||||
/// false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
bool HasPart(IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the given <see cref="IBodyPart"/> from this body,
|
|
||||||
/// dropping other <see cref="IBodyPart"/> if they were hanging
|
|
||||||
/// off of it.
|
|
||||||
/// <param name="part">The part to remove.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if the part was removed, false otherwise
|
|
||||||
/// even if the part was already removed previously.
|
|
||||||
/// </returns>
|
|
||||||
/// </summary>
|
|
||||||
bool RemovePart(IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the body part in slot <see cref="slotId"/> from this body,
|
|
||||||
/// if one exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="slotId">The slot to remove it from.</param>
|
|
||||||
/// <returns>true if the part was removed, false otherwise.</returns>
|
|
||||||
bool RemovePart(string slotId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the body part from this body, if one exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">The part to remove from this body.</param>
|
|
||||||
/// <param name="slotId">The slot that the part was in, if any.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if <see cref="part"/> was removed, false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
bool RemovePart(IBodyPart part, [NotNullWhen(true)] out BodyPartSlot? slotId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disconnects the given <see cref="IBodyPart"/> reference, potentially
|
|
||||||
/// dropping other <see cref="IBodyPart">BodyParts</see> if they
|
|
||||||
/// were hanging off of it.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="slot">The part to drop.</param>
|
|
||||||
/// <param name="dropped">
|
|
||||||
/// All of the parts that were dropped, including the one in
|
|
||||||
/// <see cref="slot"/>.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if the part was dropped, false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
bool TryDropPart(BodyPartSlot slot, [NotNullWhen(true)] out Dictionary<BodyPartSlot, IBodyPart>? dropped);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Recursively searches for if <see cref="part"/> is connected to
|
|
||||||
/// the center.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">The body part to find the center for.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if it is connected to the center, false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
bool ConnectedToCenter(IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns whether the given part slot exists in this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="slot">The slot to check for.</param>
|
|
||||||
/// <returns>true if the slot exists in this body, false otherwise.</returns>
|
|
||||||
bool HasSlot(string slot);
|
|
||||||
|
|
||||||
BodyPartSlot? GetSlot(IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the slot that the given <see cref="IBodyPart"/> resides in.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">
|
|
||||||
/// The <see cref="IBodyPart"/> to find the slot for.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="slot">The slot found, if any.</param>
|
|
||||||
/// <returns>true if a slot was found, false otherwise</returns>
|
|
||||||
bool TryGetSlot(IBodyPart part, [NotNullWhen(true)] out BodyPartSlot? slot);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the <see cref="IBodyPart"/> in the given
|
|
||||||
/// <see cref="slotId"/> if one exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="slotId">The part slot to search in.</param>
|
|
||||||
/// <param name="result">The body part in that slot, if any.</param>
|
|
||||||
/// <returns>true if found, false otherwise.</returns>
|
|
||||||
bool TryGetPart(string slotId, [NotNullWhen(true)] out IBodyPart? result);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a slot of the specified type exists on this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The type to check for.</param>
|
|
||||||
/// <returns>true if present, false otherwise.</returns>
|
|
||||||
bool HasSlotOfType(BodyPartType type);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all slots of the specified type on this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The type to check for.</param>
|
|
||||||
/// <returns>An enumerable of the found slots.</returns>
|
|
||||||
IEnumerable<BodyPartSlot> GetSlotsOfType(BodyPartType type);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a part of the specified type exists on this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The type to check for.</param>
|
|
||||||
/// <returns>true if present, false otherwise.</returns>
|
|
||||||
bool HasPartOfType(BodyPartType type);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all slots of the specified type on this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The type to check for.</param>
|
|
||||||
/// <returns>An enumerable of the found slots.</returns>
|
|
||||||
IEnumerable<IBodyPart> GetPartsOfType(BodyPartType type);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds all <see cref="IBodyPart"/>s with the given property in
|
|
||||||
/// this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <type name="type">The property type to look for.</type>
|
|
||||||
/// <returns>A list of parts with that property.</returns>
|
|
||||||
IEnumerable<(IBodyPart part, IBodyPartProperty property)> GetPartsWithProperty(Type type);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds all <see cref="IBodyPart"/>s with the given property in this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The property type to look for.</typeparam>
|
|
||||||
/// <returns>A list of parts with that property.</returns>
|
|
||||||
IEnumerable<(IBodyPart part, T property)> GetPartsWithProperty<T>() where T : class, IBodyPartProperty;
|
|
||||||
|
|
||||||
// TODO BODY Make a slot object that makes sense to the human mind, and make it serializable. Imagine the possibilities!
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves the slot at the given index.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">The index to look in.</param>
|
|
||||||
/// <returns>A pair of the slot name and part type occupying it.</returns>
|
|
||||||
BodyPartSlot SlotAt(int index);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves the part at the given index.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">The index to look in.</param>
|
|
||||||
/// <returns>A pair of the part name and body part occupying it.</returns>
|
|
||||||
KeyValuePair<IBodyPart, BodyPartSlot> PartAt(int index);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gibs this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="gibParts">
|
|
||||||
/// Whether or not to also gib this body's parts.
|
|
||||||
/// </param>
|
|
||||||
void Gib(bool gibParts = false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ 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.Part.Property;
|
||||||
using Content.Shared.Body.Preset;
|
using Content.Shared.Body.Preset;
|
||||||
@@ -25,7 +26,7 @@ using Robust.Shared.ViewVariables;
|
|||||||
namespace Content.Shared.Body.Components
|
namespace Content.Shared.Body.Components
|
||||||
{
|
{
|
||||||
// TODO BODY Damage methods for collections of IDamageableComponents
|
// TODO BODY Damage methods for collections of IDamageableComponents
|
||||||
public abstract class SharedBodyComponent : Component, IBody, ISerializationHooks
|
public abstract class SharedBodyComponent : Component, IBodyPartContainer, ISerializationHooks
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
@@ -55,13 +56,13 @@ namespace Content.Shared.Body.Components
|
|||||||
private Dictionary<string, BodyPartSlot> SlotIds { get; } = new();
|
private Dictionary<string, BodyPartSlot> SlotIds { get; } = new();
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private Dictionary<IBodyPart, BodyPartSlot> SlotParts { get; } = new();
|
private Dictionary<SharedBodyPartComponent, BodyPartSlot> SlotParts { get; } = new();
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IEnumerable<BodyPartSlot> Slots => SlotIds.Values;
|
public IEnumerable<BodyPartSlot> Slots => SlotIds.Values;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IEnumerable<KeyValuePair<IBodyPart, BodyPartSlot>> Parts => SlotParts;
|
public IEnumerable<KeyValuePair<SharedBodyPartComponent, BodyPartSlot>> Parts => SlotParts;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IEnumerable<BodyPartSlot> EmptySlots => Slots.Where(slot => slot.Part == null);
|
public IEnumerable<BodyPartSlot> EmptySlots => Slots.Where(slot => slot.Part == null);
|
||||||
@@ -71,7 +72,7 @@ namespace Content.Shared.Body.Components
|
|||||||
? SlotIds.GetValueOrDefault(centerSlot)
|
? SlotIds.GetValueOrDefault(centerSlot)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
public IBodyPart? CenterPart => CenterSlot?.Part;
|
public SharedBodyPartComponent? CenterPart => CenterSlot?.Part;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -119,9 +120,9 @@ namespace Content.Shared.Body.Components
|
|||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<BodyPartSlot, IBodyPart> GetHangingParts(BodyPartSlot from)
|
private Dictionary<BodyPartSlot, SharedBodyPartComponent> GetHangingParts(BodyPartSlot from)
|
||||||
{
|
{
|
||||||
var hanging = new Dictionary<BodyPartSlot, IBodyPart>();
|
var hanging = new Dictionary<BodyPartSlot, SharedBodyPartComponent>();
|
||||||
|
|
||||||
foreach (var connection in from.Connections)
|
foreach (var connection in from.Connections)
|
||||||
{
|
{
|
||||||
@@ -135,7 +136,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return hanging;
|
return hanging;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool CanAddPart(string slotId, IBodyPart part)
|
protected virtual bool CanAddPart(string slotId, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
if (!SlotIds.TryGetValue(slotId, out var slot) ||
|
if (!SlotIds.TryGetValue(slotId, out var slot) ||
|
||||||
slot.CanAddPart(part))
|
slot.CanAddPart(part))
|
||||||
@@ -146,7 +147,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnAddPart(BodyPartSlot slot, IBodyPart part)
|
protected virtual void OnAddPart(BodyPartSlot slot, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
SlotParts[part] = slot;
|
SlotParts[part] = slot;
|
||||||
part.Body = this;
|
part.Body = this;
|
||||||
@@ -162,7 +163,7 @@ namespace Content.Shared.Body.Components
|
|||||||
OnBodyChanged();
|
OnBodyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnRemovePart(BodyPartSlot slot, IBodyPart part)
|
protected virtual void OnRemovePart(BodyPartSlot slot, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
SlotParts.Remove(part);
|
SlotParts.Remove(part);
|
||||||
|
|
||||||
@@ -203,7 +204,8 @@ namespace Content.Shared.Body.Components
|
|||||||
OnBodyChanged();
|
OnBodyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryAddPart(string slotId, IBodyPart part)
|
// TODO BODY Sensible templates
|
||||||
|
public bool TryAddPart(string slotId, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(part);
|
DebugTools.AssertNotNull(part);
|
||||||
DebugTools.AssertNotNull(slotId);
|
DebugTools.AssertNotNull(slotId);
|
||||||
@@ -217,7 +219,7 @@ namespace Content.Shared.Body.Components
|
|||||||
slot.TryAddPart(part);
|
slot.TryAddPart(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPart(string slotId, IBodyPart part)
|
public void SetPart(string slotId, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
if (!SlotIds.TryGetValue(slotId, out var slot))
|
if (!SlotIds.TryGetValue(slotId, out var slot))
|
||||||
{
|
{
|
||||||
@@ -236,14 +238,14 @@ namespace Content.Shared.Body.Components
|
|||||||
slot.Part != null;
|
slot.Part != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasPart(IBodyPart part)
|
public bool HasPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(part);
|
DebugTools.AssertNotNull(part);
|
||||||
|
|
||||||
return SlotParts.ContainsKey(part);
|
return SlotParts.ContainsKey(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemovePart(IBodyPart part)
|
public bool RemovePart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(part);
|
DebugTools.AssertNotNull(part);
|
||||||
|
|
||||||
@@ -259,7 +261,7 @@ namespace Content.Shared.Body.Components
|
|||||||
slot.RemovePart();
|
slot.RemovePart();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemovePart(IBodyPart part, [NotNullWhen(true)] out BodyPartSlot? slotId)
|
public bool RemovePart(SharedBodyPartComponent part, [NotNullWhen(true)] out BodyPartSlot? slotId)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(part);
|
DebugTools.AssertNotNull(part);
|
||||||
|
|
||||||
@@ -279,7 +281,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryDropPart(BodyPartSlot slot, [NotNullWhen(true)] out Dictionary<BodyPartSlot, IBodyPart>? dropped)
|
public bool TryDropPart(BodyPartSlot slot, [NotNullWhen(true)] out Dictionary<BodyPartSlot, SharedBodyPartComponent>? dropped)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(slot);
|
DebugTools.AssertNotNull(slot);
|
||||||
|
|
||||||
@@ -304,7 +306,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ConnectedToCenter(IBodyPart part)
|
public bool ConnectedToCenter(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
return TryGetSlot(part, out var result) &&
|
return TryGetSlot(part, out var result) &&
|
||||||
ConnectedToCenterPartRecursion(result);
|
ConnectedToCenterPartRecursion(result);
|
||||||
@@ -343,7 +345,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return SlotIds.ContainsKey(slot);
|
return SlotIds.ContainsKey(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IBodyPart> GetParts()
|
public IEnumerable<SharedBodyPartComponent> GetParts()
|
||||||
{
|
{
|
||||||
foreach (var slot in SlotIds.Values)
|
foreach (var slot in SlotIds.Values)
|
||||||
{
|
{
|
||||||
@@ -354,7 +356,7 @@ namespace Content.Shared.Body.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetPart(string slotId, [NotNullWhen(true)] out IBodyPart? result)
|
public bool TryGetPart(string slotId, [NotNullWhen(true)] out SharedBodyPartComponent? result)
|
||||||
{
|
{
|
||||||
result = null;
|
result = null;
|
||||||
|
|
||||||
@@ -367,7 +369,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return SlotIds.GetValueOrDefault(id);
|
return SlotIds.GetValueOrDefault(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BodyPartSlot? GetSlot(IBodyPart part)
|
public BodyPartSlot? GetSlot(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
return SlotParts.GetValueOrDefault(part);
|
return SlotParts.GetValueOrDefault(part);
|
||||||
}
|
}
|
||||||
@@ -377,12 +379,12 @@ namespace Content.Shared.Body.Components
|
|||||||
return (slot = GetSlot(slotId)) != null;
|
return (slot = GetSlot(slotId)) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetSlot(IBodyPart part, [NotNullWhen(true)] out BodyPartSlot? slot)
|
public bool TryGetSlot(SharedBodyPartComponent part, [NotNullWhen(true)] out BodyPartSlot? slot)
|
||||||
{
|
{
|
||||||
return (slot = GetSlot(part)) != null;
|
return (slot = GetSlot(part)) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetPartConnections(string slotId, [NotNullWhen(true)] out List<IBodyPart>? connections)
|
public bool TryGetPartConnections(string slotId, [NotNullWhen(true)] out List<SharedBodyPartComponent>? connections)
|
||||||
{
|
{
|
||||||
if (!SlotIds.TryGetValue(slotId, out var slot))
|
if (!SlotIds.TryGetValue(slotId, out var slot))
|
||||||
{
|
{
|
||||||
@@ -390,7 +392,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
connections = new List<IBodyPart>();
|
connections = new List<SharedBodyPartComponent>();
|
||||||
foreach (var connection in slot.Connections)
|
foreach (var connection in slot.Connections)
|
||||||
{
|
{
|
||||||
if (connection.Part != null)
|
if (connection.Part != null)
|
||||||
@@ -439,7 +441,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IBodyPart> GetPartsOfType(BodyPartType type)
|
public IEnumerable<SharedBodyPartComponent> GetPartsOfType(BodyPartType type)
|
||||||
{
|
{
|
||||||
foreach (var slot in GetSlotsOfType(type))
|
foreach (var slot in GetSlotsOfType(type))
|
||||||
{
|
{
|
||||||
@@ -450,7 +452,8 @@ namespace Content.Shared.Body.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<(IBodyPart part, IBodyPartProperty property)> GetPartsWithProperty(Type type)
|
/// <returns>A list of parts with that property.</returns>
|
||||||
|
public IEnumerable<(SharedBodyPartComponent part, IBodyPartProperty property)> GetPartsWithProperty(Type type)
|
||||||
{
|
{
|
||||||
foreach (var slot in SlotIds.Values)
|
foreach (var slot in SlotIds.Values)
|
||||||
{
|
{
|
||||||
@@ -461,7 +464,7 @@ namespace Content.Shared.Body.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<(IBodyPart part, T property)> GetPartsWithProperty<T>() where T : class, IBodyPartProperty
|
public IEnumerable<(SharedBodyPartComponent part, T property)> GetPartsWithProperty<T>() where T : class, IBodyPartProperty
|
||||||
{
|
{
|
||||||
foreach (var part in SlotParts.Keys)
|
foreach (var part in SlotParts.Keys)
|
||||||
{
|
{
|
||||||
@@ -509,9 +512,6 @@ namespace Content.Shared.Body.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the layout of this body changes.
|
|
||||||
/// </summary>
|
|
||||||
private void OnBodyChanged()
|
private void OnBodyChanged()
|
||||||
{
|
{
|
||||||
// Calculate move speed based on this body.
|
// Calculate move speed based on this body.
|
||||||
@@ -523,19 +523,7 @@ namespace Content.Shared.Body.Components
|
|||||||
Dirty();
|
Dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public float DistanceToNearestFoot(SharedBodyPartComponent source)
|
||||||
/// Returns the combined length of the distance to the nearest
|
|
||||||
/// <see cref="IBodyPart"/> that is a foot.
|
|
||||||
/// If you consider a <see cref="IBody"/> a node map, then it will
|
|
||||||
/// look for a foot node from the given node. It can only search
|
|
||||||
/// through <see cref="IBodyPart"/>s with an
|
|
||||||
/// <see cref="ExtensionComponent"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// The distance to the foot if found, <see cref="float.MinValue"/>
|
|
||||||
/// otherwise.
|
|
||||||
/// </returns>
|
|
||||||
public float DistanceToNearestFoot(IBodyPart source)
|
|
||||||
{
|
{
|
||||||
if (source.PartType == BodyPartType.Foot &&
|
if (source.PartType == BodyPartType.Foot &&
|
||||||
source.TryGetProperty<ExtensionComponent>(out var extension))
|
source.TryGetProperty<ExtensionComponent>(out var extension))
|
||||||
@@ -546,7 +534,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return LookForFootRecursion(source);
|
return LookForFootRecursion(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float LookForFootRecursion(IBodyPart current, HashSet<BodyPartSlot>? searched = null)
|
private float LookForFootRecursion(SharedBodyPartComponent current, HashSet<BodyPartSlot>? searched = null)
|
||||||
{
|
{
|
||||||
searched ??= new HashSet<BodyPartSlot>();
|
searched ??= new HashSet<BodyPartSlot>();
|
||||||
|
|
||||||
@@ -555,13 +543,11 @@ namespace Content.Shared.Body.Components
|
|||||||
return float.MinValue;
|
return float.MinValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all connected parts if the current part has an extension property
|
|
||||||
if (!TryGetSlot(current, out var slot))
|
if (!TryGetSlot(current, out var slot))
|
||||||
{
|
{
|
||||||
return float.MinValue;
|
return float.MinValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a connected BodyPart is a foot, return this BodyPart's length.
|
|
||||||
foreach (var connection in slot.Connections)
|
foreach (var connection in slot.Connections)
|
||||||
{
|
{
|
||||||
if (connection.PartType == BodyPartType.Foot &&
|
if (connection.PartType == BodyPartType.Foot &&
|
||||||
@@ -571,8 +557,6 @@ namespace Content.Shared.Body.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, get the recursion values of all connected BodyParts and
|
|
||||||
// store them in a list.
|
|
||||||
var distances = new List<float>();
|
var distances = new List<float>();
|
||||||
foreach (var connection in slot.Connections)
|
foreach (var connection in slot.Connections)
|
||||||
{
|
{
|
||||||
@@ -589,8 +573,6 @@ namespace Content.Shared.Body.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If one or more of the searches found a foot, return the smallest one
|
|
||||||
// and add this ones length.
|
|
||||||
if (distances.Count > 0)
|
if (distances.Count > 0)
|
||||||
{
|
{
|
||||||
return distances.Min<float>() + extProperty.Distance;
|
return distances.Min<float>() + extProperty.Distance;
|
||||||
@@ -605,7 +587,7 @@ namespace Content.Shared.Body.Components
|
|||||||
return SlotIds.Values.ElementAt(index);
|
return SlotIds.Values.ElementAt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyValuePair<IBodyPart, BodyPartSlot> PartAt(int index)
|
public KeyValuePair<SharedBodyPartComponent, BodyPartSlot> PartAt(int index)
|
||||||
{
|
{
|
||||||
return SlotParts.ElementAt(index);
|
return SlotParts.ElementAt(index);
|
||||||
}
|
}
|
||||||
@@ -664,12 +646,68 @@ 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]
|
||||||
public class BodyComponentState : ComponentState
|
public class BodyComponentState : ComponentState
|
||||||
{
|
{
|
||||||
private Dictionary<string, IBodyPart>? _parts;
|
private Dictionary<string, SharedBodyPartComponent>? _parts;
|
||||||
|
|
||||||
public readonly (string slot, EntityUid partId)[] PartIds;
|
public readonly (string slot, EntityUid partId)[] PartIds;
|
||||||
|
|
||||||
@@ -678,7 +716,7 @@ namespace Content.Shared.Body.Components
|
|||||||
PartIds = partIds;
|
PartIds = partIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, IBodyPart> Parts(IEntityManager? entityManager = null)
|
public Dictionary<string, SharedBodyPartComponent> Parts(IEntityManager? entityManager = null)
|
||||||
{
|
{
|
||||||
if (_parts != null)
|
if (_parts != null)
|
||||||
{
|
{
|
||||||
@@ -687,7 +725,7 @@ namespace Content.Shared.Body.Components
|
|||||||
|
|
||||||
entityManager ??= IoCManager.Resolve<IEntityManager>();
|
entityManager ??= IoCManager.Resolve<IEntityManager>();
|
||||||
|
|
||||||
var parts = new Dictionary<string, IBodyPart>(PartIds.Length);
|
var parts = new Dictionary<string, SharedBodyPartComponent>(PartIds.Length);
|
||||||
|
|
||||||
foreach (var (slot, partId) in PartIds)
|
foreach (var (slot, partId) in PartIds)
|
||||||
{
|
{
|
||||||
@@ -696,7 +734,7 @@ namespace Content.Shared.Body.Components
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entity.TryGetComponent(out IBodyPart? part))
|
if (!entity.TryGetComponent(out SharedBodyPartComponent? part))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,178 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Content.Shared.Body.Behavior;
|
|
||||||
using Content.Shared.Body.Components;
|
|
||||||
using Content.Shared.Body.Part;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Shared.Body.Mechanism
|
|
||||||
{
|
|
||||||
public interface IMechanism : IComponent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The body that owns the <see cref="IBodyPart"/> in which this
|
|
||||||
/// <see cref="IMechanism"/> is in.
|
|
||||||
/// </summary>
|
|
||||||
IBody? Body { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The part in which this <see cref="IMechanism"/> is in.
|
|
||||||
/// </summary>
|
|
||||||
IBodyPart? Part { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The behaviors attached to this <see cref="IMechanism"/>
|
|
||||||
/// mapped by their type.
|
|
||||||
/// </summary>
|
|
||||||
IReadOnlyDictionary<Type, IMechanismBehavior> Behaviors { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Max HP of this <see cref="IMechanism"/>.
|
|
||||||
/// </summary>
|
|
||||||
int MaxDurability { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Current HP of this <see cref="IMechanism"/>.
|
|
||||||
/// </summary>
|
|
||||||
int CurrentDurability { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// At what HP this <see cref="IMechanism"/> is completely destroyed.
|
|
||||||
/// </summary>
|
|
||||||
int DestroyThreshold { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Armor of this <see cref="IMechanism"/> against attacks.
|
|
||||||
/// </summary>
|
|
||||||
int Resistance { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines a handful of things - mostly whether this
|
|
||||||
/// <see cref="IMechanism"/> can fit into a <see cref="IBodyPart"/>.
|
|
||||||
/// </summary>
|
|
||||||
// TODO BODY OnSizeChanged
|
|
||||||
int Size { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// What kind of <see cref="IBodyPart"/> this
|
|
||||||
/// <see cref="IMechanism"/> can be easily installed into.
|
|
||||||
/// </summary>
|
|
||||||
BodyPartCompatibility Compatibility { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a <see cref="IMechanismBehavior"/> if this
|
|
||||||
/// <see cref="IMechanism"/> does not have it already.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The behavior type to add.</typeparam>
|
|
||||||
/// <returns>
|
|
||||||
/// True if the behavior already existed, false if it had to be created.
|
|
||||||
/// </returns>
|
|
||||||
bool EnsureBehavior<T>(out T behavior) where T : IMechanismBehavior, new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if this <see cref="IMechanism"/> has the specified
|
|
||||||
/// <see cref="IMechanismBehavior"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">
|
|
||||||
/// The type of <see cref="IMechanismBehavior"/> to check for.
|
|
||||||
/// </typeparam>
|
|
||||||
/// <returns>
|
|
||||||
/// true if it has the <see cref="IMechanismBehavior"/>, false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
bool HasBehavior<T>() where T : IMechanismBehavior;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the specified <see cref="IMechanismBehavior"/> from this
|
|
||||||
/// <see cref="IMechanism"/> if it has it.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">
|
|
||||||
/// The type of <see cref="IMechanismBehavior"/> to remove.
|
|
||||||
/// </typeparam>
|
|
||||||
/// <returns>true if it was removed, false otherwise.</returns>
|
|
||||||
bool TryRemoveBehavior<T>() where T : IMechanismBehavior;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Runs an update cycle for this <see cref="IMechanism"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="frameTime">
|
|
||||||
/// The amount of seconds that passed since the last update.
|
|
||||||
/// </param>
|
|
||||||
void Update(float frameTime);
|
|
||||||
|
|
||||||
// TODO BODY Turn these into event listeners so they dont need to be exposed
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the containing <see cref="IBodyPart"/> is attached to a
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// 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 this <see cref="IMechanism"/> was added to.
|
|
||||||
/// </param>
|
|
||||||
void AddedToBody(IBody body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IMechanism"/> is
|
|
||||||
/// added into a <see cref="IBodyPart"/> that is not attached to a
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// 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 this <see cref="IMechanism"/> was added to.
|
|
||||||
/// </param>
|
|
||||||
void AddedToPart(IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IMechanism"/> is added to a
|
|
||||||
/// <see cref="IBodyPart"/> that is attached to a <see cref="IBody"/>.
|
|
||||||
/// 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 this <see cref="IMechanism"/> was added to.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="part">
|
|
||||||
/// The part that this <see cref="IMechanism"/> was added to.
|
|
||||||
/// </param>
|
|
||||||
void AddedToPartInBody(IBody body, IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IBodyPart"/> is removed from a
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// 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 this <see cref="IMechanism"/> was removed from.
|
|
||||||
/// </param>
|
|
||||||
void RemovedFromBody(IBody old);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IMechanism"/> is
|
|
||||||
/// removed from a <see cref="IBodyPart"/> that is not attached to a
|
|
||||||
/// <see cref="IBody"/>.
|
|
||||||
/// 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 this <see cref="IMechanism"/> was removed from.
|
|
||||||
/// </param>
|
|
||||||
void RemovedFromPart(IBodyPart old);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the parent <see cref="IMechanism"/> is removed from a
|
|
||||||
/// <see cref="IBodyPart"/> that is attached to a <see cref="IBody"/>.
|
|
||||||
/// 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 this <see cref="IMechanism"/> was removed from.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="oldPart">
|
|
||||||
/// The part that this <see cref="IMechanism"/> was removed from.
|
|
||||||
/// </param>
|
|
||||||
void RemovedFromPartInBody(IBody oldBody, IBodyPart oldPart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,7 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
|
|
||||||
foreach (var mechanism in ComponentManager.EntityQuery<IMechanism>(true))
|
foreach (var mechanism in ComponentManager.EntityQuery<SharedMechanismComponent>(true))
|
||||||
{
|
{
|
||||||
mechanism.Update(frameTime);
|
mechanism.Update(frameTime);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,23 +14,23 @@ using Robust.Shared.Utility;
|
|||||||
|
|
||||||
namespace Content.Shared.Body.Mechanism
|
namespace Content.Shared.Body.Mechanism
|
||||||
{
|
{
|
||||||
public abstract class SharedMechanismComponent : Component, IMechanism, ISerializationHooks
|
public abstract class SharedMechanismComponent : Component, ISerializationHooks
|
||||||
{
|
{
|
||||||
public override string Name => "Mechanism";
|
public override string Name => "Mechanism";
|
||||||
|
|
||||||
protected readonly Dictionary<int, object> OptionsCache = new();
|
protected readonly Dictionary<int, object> OptionsCache = new();
|
||||||
protected IBody? BodyCache;
|
protected SharedBodyComponent? BodyCache;
|
||||||
protected int IdHash;
|
protected int IdHash;
|
||||||
protected IEntity? PerformerCache;
|
protected IEntity? PerformerCache;
|
||||||
private IBodyPart? _part;
|
private SharedBodyPartComponent? _part;
|
||||||
|
|
||||||
[DataField("behaviors", serverOnly: true)] private HashSet<IMechanismBehavior> _behaviorTypes = new();
|
[DataField("behaviors", serverOnly: true)] private HashSet<SharedMechanismBehavior> _behaviorTypes = new();
|
||||||
|
|
||||||
private readonly Dictionary<Type, IMechanismBehavior> _behaviors = new();
|
private readonly Dictionary<Type, SharedMechanismBehavior> _behaviors = new();
|
||||||
|
|
||||||
public IBody? Body => Part?.Body;
|
public SharedBodyComponent? Body => Part?.Body;
|
||||||
|
|
||||||
public IBodyPart? Part
|
public SharedBodyPartComponent? Part
|
||||||
{
|
{
|
||||||
get => _part;
|
get => _part;
|
||||||
set
|
set
|
||||||
@@ -69,7 +69,7 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IReadOnlyDictionary<Type, IMechanismBehavior> Behaviors => _behaviors;
|
public IReadOnlyDictionary<Type, SharedMechanismBehavior> Behaviors => _behaviors;
|
||||||
|
|
||||||
[DataField("maxDurability")] public int MaxDurability { get; set; } = 10;
|
[DataField("maxDurability")] public int MaxDurability { get; set; } = 10;
|
||||||
|
|
||||||
@@ -82,8 +82,16 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
[DataField("resistance")] public int Resistance { get; set; } = 0;
|
[DataField("resistance")] public int Resistance { get; set; } = 0;
|
||||||
|
|
||||||
// TODO BODY OnSizeChanged
|
// TODO BODY OnSizeChanged
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether this
|
||||||
|
/// <see cref="SharedMechanismComponent"/> can fit into a <see cref="SharedBodyPartComponent"/>.
|
||||||
|
/// </summary>
|
||||||
[DataField("size")] public int Size { get; set; } = 1;
|
[DataField("size")] public int Size { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// What kind of <see cref="SharedBodyPartComponent"/> this
|
||||||
|
/// <see cref="SharedMechanismComponent"/> can be easily installed into.
|
||||||
|
/// </summary>
|
||||||
[DataField("compatibility")]
|
[DataField("compatibility")]
|
||||||
public BodyPartCompatibility Compatibility { get; set; } = BodyPartCompatibility.Universal;
|
public BodyPartCompatibility Compatibility { get; set; } = BodyPartCompatibility.Universal;
|
||||||
|
|
||||||
@@ -128,7 +136,7 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool EnsureBehavior<T>(out T behavior) where T : IMechanismBehavior, new()
|
public bool EnsureBehavior<T>(out T behavior) where T : SharedMechanismBehavior, new()
|
||||||
{
|
{
|
||||||
if (_behaviors.TryGetValue(typeof(T), out var rawBehavior))
|
if (_behaviors.TryGetValue(typeof(T), out var rawBehavior))
|
||||||
{
|
{
|
||||||
@@ -144,12 +152,12 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasBehavior<T>() where T : IMechanismBehavior
|
public bool HasBehavior<T>() where T : SharedMechanismBehavior
|
||||||
{
|
{
|
||||||
return _behaviors.ContainsKey(typeof(T));
|
return _behaviors.ContainsKey(typeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryRemoveBehavior<T>() where T : IMechanismBehavior
|
public bool TryRemoveBehavior<T>() where T : SharedMechanismBehavior
|
||||||
{
|
{
|
||||||
return _behaviors.Remove(typeof(T));
|
return _behaviors.Remove(typeof(T));
|
||||||
}
|
}
|
||||||
@@ -162,7 +170,8 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddedToBody(IBody body)
|
// TODO BODY Turn these into event listeners so they dont need to be exposed
|
||||||
|
public void AddedToBody(SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(Body);
|
DebugTools.AssertNotNull(Body);
|
||||||
DebugTools.AssertNotNull(body);
|
DebugTools.AssertNotNull(body);
|
||||||
@@ -173,7 +182,7 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddedToPart(IBodyPart part)
|
public void AddedToPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(Part);
|
DebugTools.AssertNotNull(Part);
|
||||||
DebugTools.AssertNotNull(part);
|
DebugTools.AssertNotNull(part);
|
||||||
@@ -186,7 +195,7 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddedToPartInBody(IBody body, IBodyPart part)
|
public void AddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(Body);
|
DebugTools.AssertNotNull(Body);
|
||||||
DebugTools.AssertNotNull(body);
|
DebugTools.AssertNotNull(body);
|
||||||
@@ -201,7 +210,7 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovedFromBody(IBody old)
|
public void RemovedFromBody(SharedBodyComponent old)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNull(Body);
|
DebugTools.AssertNull(Body);
|
||||||
DebugTools.AssertNotNull(old);
|
DebugTools.AssertNotNull(old);
|
||||||
@@ -212,7 +221,7 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovedFromPart(IBodyPart old)
|
public void RemovedFromPart(SharedBodyPartComponent old)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNull(Part);
|
DebugTools.AssertNull(Part);
|
||||||
DebugTools.AssertNotNull(old);
|
DebugTools.AssertNotNull(old);
|
||||||
@@ -225,7 +234,7 @@ namespace Content.Shared.Body.Mechanism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovedFromPartInBody(IBody oldBody, IBodyPart oldPart)
|
public void RemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNull(Body);
|
DebugTools.AssertNull(Body);
|
||||||
DebugTools.AssertNotNull(oldBody);
|
DebugTools.AssertNotNull(oldBody);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Robust.Shared.Serialization;
|
|||||||
namespace Content.Shared.Body.Part
|
namespace Content.Shared.Body.Part
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether two <see cref="IBodyPart"/>s can connect.
|
/// Determines whether two <see cref="SharedBodyPartComponent"/>s can connect.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum BodyPartCompatibility
|
public enum BodyPartCompatibility
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using Content.Shared.Body.Part.Property;
|
|
||||||
|
|
||||||
namespace Content.Shared.Body.Part
|
|
||||||
{
|
|
||||||
public static class BodyPartExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the given <see cref="IBodyPart"/> has the specified property.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">The <see cref="IBodyPart"/> to check in.</param>
|
|
||||||
/// <param name="type">
|
|
||||||
/// The type of <see cref="IBodyPartProperty"/> to check for.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>true if found, false otherwise.</returns>
|
|
||||||
public static bool HasProperty(this IBodyPart part, Type type)
|
|
||||||
{
|
|
||||||
return part.Owner.HasComponent(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the given <see cref="IBodyPart"/> has the specified property.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">The <see cref="IBodyPart"/> to check in.</param>
|
|
||||||
/// <typeparam name="T">
|
|
||||||
/// The type of <see cref="IBodyPartProperty"/> to check for.
|
|
||||||
/// </typeparam>
|
|
||||||
/// <returns>true if found, false otherwise.</returns>
|
|
||||||
public static bool HasProperty<T>(this IBodyPart part) where T : class, IBodyPartProperty
|
|
||||||
{
|
|
||||||
return part.HasProperty(typeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to retrieve the <see cref="IBodyPartProperty"/> with the
|
|
||||||
/// specified type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">The <see cref="IBodyPart"/> to search in.</param>
|
|
||||||
/// <param name="type">
|
|
||||||
/// The type of <see cref="IBodyPartProperty"/> to search for.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="property">
|
|
||||||
/// The property, if it was found. Null otherwise.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if a component with the specified type was found, false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
public static bool TryGetProperty(this IBodyPart part, Type type,
|
|
||||||
[NotNullWhen(true)] out IBodyPartProperty? property)
|
|
||||||
{
|
|
||||||
if (!part.Owner.TryGetComponent(type, out var component))
|
|
||||||
{
|
|
||||||
property = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (property = component as IBodyPartProperty) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to retrieve the <see cref="IBodyPartProperty"/> with the
|
|
||||||
/// specified type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">The <see cref="IBodyPart"/> to search in.</param>
|
|
||||||
/// <typeparam name="T">
|
|
||||||
/// The type of <see cref="IBodyPartProperty"/> to search for.
|
|
||||||
/// </typeparam>
|
|
||||||
/// <param name="property">
|
|
||||||
/// The property, if it was found. Null otherwise.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// true if a component with the specified type was found, false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
public static bool TryGetProperty<T>(this IBodyPart part, [NotNullWhen(true)] out T? property) where T : class, IBodyPartProperty
|
|
||||||
{
|
|
||||||
return part.Owner.TryGetComponent(out property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@ using Robust.Shared.Serialization;
|
|||||||
namespace Content.Shared.Body.Part
|
namespace Content.Shared.Body.Part
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the symmetry of a <see cref="IBodyPart"/>.
|
/// Defines the symmetry of a <see cref="SharedBodyPartComponent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum BodyPartSymmetry
|
public enum BodyPartSymmetry
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Robust.Shared.Serialization;
|
|||||||
namespace Content.Shared.Body.Part
|
namespace Content.Shared.Body.Part
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the type of a <see cref="IBodyPart"/>.
|
/// Defines the type of a <see cref="SharedBodyPartComponent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum BodyPartType
|
public enum BodyPartType
|
||||||
|
|||||||
@@ -1,131 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Content.Shared.Body.Components;
|
|
||||||
using Content.Shared.Body.Mechanism;
|
|
||||||
using Content.Shared.Body.Surgery;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Map;
|
|
||||||
|
|
||||||
namespace Content.Shared.Body.Part
|
|
||||||
{
|
|
||||||
public interface IBodyPart : IComponent, IBodyPartContainer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="IBody"/> to which this <see cref="IBodyPart"/> is
|
|
||||||
/// attached to.
|
|
||||||
/// </summary>
|
|
||||||
IBody? Body { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The string to show when displaying this part's name to players.
|
|
||||||
/// </summary>
|
|
||||||
string DisplayName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="BodyPartType"/> that this <see cref="IBodyPart"/> is considered
|
|
||||||
/// to be.
|
|
||||||
/// For example, <see cref="BodyPartType.Arm"/>.
|
|
||||||
/// </summary>
|
|
||||||
BodyPartType PartType { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines how many mechanisms can be fit inside this
|
|
||||||
/// <see cref="IBodyPart"/>.
|
|
||||||
/// </summary>
|
|
||||||
int Size { get; }
|
|
||||||
|
|
||||||
// TODO BODY Mechanisms occupying different parts at the body level
|
|
||||||
/// <summary>
|
|
||||||
/// Collection of all <see cref="IMechanism"/>s currently inside this
|
|
||||||
/// <see cref="IBodyPart"/>.
|
|
||||||
/// To add and remove from this list see <see cref="TryAddMechanism"/> and
|
|
||||||
/// <see cref="RemoveMechanism"/>
|
|
||||||
/// </summary>
|
|
||||||
IReadOnlyCollection<IMechanism> Mechanisms { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether or not the owning <see cref="Body"/> will die if all
|
|
||||||
/// <see cref="IBodyPart"/>s of this type are removed from it.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsVital { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The symmetry of this <see cref="IBodyPart"/>.
|
|
||||||
/// </summary>
|
|
||||||
public BodyPartSymmetry Symmetry { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the given <see cref="SurgeryType"/> can be used on
|
|
||||||
/// the current state of this <see cref="IBodyPart"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if it can be used, false otherwise.</returns>
|
|
||||||
bool SurgeryCheck(SurgeryType surgery);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to perform surgery on this <see cref="IBodyPart"/> with the given
|
|
||||||
/// tool.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if successful, false if there was an error.</returns>
|
|
||||||
public bool AttemptSurgery(SurgeryType toolType, IBodyPartContainer target, ISurgeon surgeon,
|
|
||||||
IEntity performer);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if another <see cref="IBodyPart"/> can be connected to this one.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part">The part to connect.</param>
|
|
||||||
/// <returns>True if it can be connected, false otherwise.</returns>
|
|
||||||
bool CanAttachPart(IBodyPart part);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a <see cref="IMechanism"/> can be added on this
|
|
||||||
/// <see cref="IBodyPart"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if it can be added, false otherwise.</returns>
|
|
||||||
bool CanAddMechanism(IMechanism mechanism);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to add a <see cref="IMechanism"/> to this body.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mechanism">The mechanism to add.</param>
|
|
||||||
/// <param name="force">
|
|
||||||
/// Whether or not to check if the mechanism is compatible.
|
|
||||||
/// Passing true does not guarantee it to be added, for example if
|
|
||||||
/// it was already added before.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>true if added, false otherwise even if it was already added.</returns>
|
|
||||||
bool TryAddMechanism(IMechanism mechanism, bool force = false);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to remove the given <see cref="mechanism"/> from this
|
|
||||||
/// <see cref="IBodyPart"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mechanism">The mechanism to remove.</param>
|
|
||||||
/// <returns>True if it was removed, false otherwise.</returns>
|
|
||||||
bool RemoveMechanism(IMechanism mechanism);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to remove the given <see cref="mechanism"/> from this
|
|
||||||
/// <see cref="IBodyPart"/> and drops it at the specified coordinates.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mechanism">The mechanism to remove.</param>
|
|
||||||
/// <param name="dropAt">The coordinates to drop it at.</param>
|
|
||||||
/// <returns>True if it was removed, false otherwise.</returns>
|
|
||||||
bool RemoveMechanism(IMechanism mechanism, EntityCoordinates dropAt);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to destroy the given <see cref="IMechanism"/> from
|
|
||||||
/// this <see cref="IBodyPart"/>.
|
|
||||||
/// The mechanism won't be deleted if it is not in this body part.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// True if the mechanism was in this body part and destroyed,
|
|
||||||
/// false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
bool DeleteMechanism(IMechanism mechanism);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gibs the body part.
|
|
||||||
/// </summary>
|
|
||||||
void Gib();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,7 @@ namespace Content.Shared.Body.Part
|
|||||||
public interface IBodyPartAdded : IComponent
|
public interface IBodyPartAdded : IComponent
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when a <see cref="IBodyPart"/> is added to the
|
/// Called when a <see cref="SharedBodyPartComponent"/> is added to the
|
||||||
/// entity owning this component.
|
/// entity owning this component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">Information about the part that was added.</param>
|
/// <param name="args">Information about the part that was added.</param>
|
||||||
@@ -20,7 +20,7 @@ namespace Content.Shared.Body.Part
|
|||||||
|
|
||||||
public class BodyPartAddedEventArgs : EventArgs
|
public class BodyPartAddedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public BodyPartAddedEventArgs(string slot, IBodyPart part)
|
public BodyPartAddedEventArgs(string slot, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
Slot = slot;
|
Slot = slot;
|
||||||
Part = part;
|
Part = part;
|
||||||
@@ -34,6 +34,6 @@ namespace Content.Shared.Body.Part
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The part that was added.
|
/// The part that was added.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBodyPart Part { get; }
|
public SharedBodyPartComponent Part { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace Content.Shared.Body.Part
|
|||||||
public interface IBodyPartRemoved
|
public interface IBodyPartRemoved
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when a <see cref="IBodyPart"/> is removed from the
|
/// Called when a <see cref="SharedBodyPartComponent"/> is removed from the
|
||||||
/// entity owning this component.
|
/// entity owning this component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">Information about the part that was removed.</param>
|
/// <param name="args">Information about the part that was removed.</param>
|
||||||
@@ -19,7 +19,7 @@ namespace Content.Shared.Body.Part
|
|||||||
|
|
||||||
public class BodyPartRemovedEventArgs : EventArgs
|
public class BodyPartRemovedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public BodyPartRemovedEventArgs(string slot, IBodyPart part)
|
public BodyPartRemovedEventArgs(string slot, SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
Slot = slot;
|
Slot = slot;
|
||||||
Part = part;
|
Part = part;
|
||||||
@@ -33,6 +33,6 @@ namespace Content.Shared.Body.Part
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The part that was removed.
|
/// The part that was removed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBodyPart Part { get; }
|
public SharedBodyPartComponent Part { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
|||||||
namespace Content.Shared.Body.Part.Property
|
namespace Content.Shared.Body.Part.Property
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Property attachable to a <see cref="IBodyPart"/>.
|
/// Property attachable to a <see cref="SharedBodyPartComponent"/>.
|
||||||
/// For example, this is used to define the speed capabilities of a leg.
|
/// 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
|
/// The movement system will look for a <see cref="LegComponent"/> on all
|
||||||
/// <see cref="IBodyPart"/>.
|
/// <see cref="SharedBodyPartComponent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BodyPartPropertyComponent : Component, IBodyPartProperty
|
public abstract class BodyPartPropertyComponent : Component, IBodyPartProperty
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
|||||||
namespace Content.Shared.Body.Part.Property
|
namespace Content.Shared.Body.Part.Property
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the length of a <see cref="IBodyPart"/>.
|
/// Defines the length of a <see cref="SharedBodyPartComponent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class ExtensionComponent : BodyPartPropertyComponent
|
public class ExtensionComponent : BodyPartPropertyComponent
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Robust.Shared.GameObjects;
|
|||||||
namespace Content.Shared.Body.Part.Property
|
namespace Content.Shared.Body.Part.Property
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a <see cref="IBodyPart"/> as being able to grasp around an entity,
|
/// Defines a <see cref="SharedBodyPartComponent"/> as being able to grasp around an entity,
|
||||||
/// for example picking up an item.
|
/// for example picking up an item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// TODO BODY Implement
|
// TODO BODY Implement
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Robust.Shared.GameObjects;
|
|||||||
namespace Content.Shared.Body.Part.Property
|
namespace Content.Shared.Body.Part.Property
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a property for a <see cref="IBodyPart"/>.
|
/// Defines a property for a <see cref="SharedBodyPartComponent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBodyPartProperty : IComponent
|
public interface IBodyPartProperty : IComponent
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
|||||||
namespace Content.Shared.Body.Part.Property
|
namespace Content.Shared.Body.Part.Property
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the speed at which a <see cref="IBodyPart"/> can move.
|
/// Defines the speed at which a <see cref="SharedBodyPartComponent"/> can move.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class LegComponent : BodyPartPropertyComponent
|
public class LegComponent : BodyPartPropertyComponent
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
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.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Body.Mechanism;
|
using Content.Shared.Body.Mechanism;
|
||||||
|
using Content.Shared.Body.Part.Property;
|
||||||
using Content.Shared.Body.Surgery;
|
using Content.Shared.Body.Surgery;
|
||||||
using Content.Shared.NetIDs;
|
using Content.Shared.NetIDs;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -17,24 +20,24 @@ using Robust.Shared.ViewVariables;
|
|||||||
|
|
||||||
namespace Content.Shared.Body.Part
|
namespace Content.Shared.Body.Part
|
||||||
{
|
{
|
||||||
public abstract class SharedBodyPartComponent : Component, IBodyPart
|
public abstract class SharedBodyPartComponent : Component, IBodyPartContainer
|
||||||
{
|
{
|
||||||
public override string Name => "BodyPart";
|
public override string Name => "BodyPart";
|
||||||
|
|
||||||
public override uint? NetID => ContentNetIDs.BODY_PART;
|
public override uint? NetID => ContentNetIDs.BODY_PART;
|
||||||
|
|
||||||
private IBody? _body;
|
private SharedBodyComponent? _body;
|
||||||
|
|
||||||
// TODO BODY Remove
|
// TODO BODY Remove
|
||||||
[DataField("mechanisms")]
|
[DataField("mechanisms")]
|
||||||
private List<string> _mechanismIds = new();
|
private readonly List<string> _mechanismIds = new();
|
||||||
public IReadOnlyList<string> MechanismIds => _mechanismIds;
|
public IReadOnlyList<string> MechanismIds => _mechanismIds;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly HashSet<IMechanism> _mechanisms = new();
|
private readonly HashSet<SharedMechanismComponent> _mechanisms = new();
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IBody? Body
|
public SharedBodyComponent? Body
|
||||||
{
|
{
|
||||||
get => _body;
|
get => _body;
|
||||||
set
|
set
|
||||||
@@ -59,13 +62,25 @@ namespace Content.Shared.Body.Part
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The string to show when displaying this part's name to players.
|
||||||
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public string DisplayName => Name;
|
public string DisplayName => Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="BodyPartType"/> that this <see cref="IBodyPart"/> is considered
|
||||||
|
/// to be.
|
||||||
|
/// For example, <see cref="BodyPartType.Arm"/>.
|
||||||
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
[DataField("partType")]
|
[DataField("partType")]
|
||||||
public BodyPartType PartType { get; private set; } = BodyPartType.Other;
|
public BodyPartType PartType { get; private set; } = BodyPartType.Other;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines how many mechanisms can be fit inside this
|
||||||
|
/// <see cref="SharedBodyPartComponent"/>.
|
||||||
|
/// </summary>
|
||||||
[ViewVariables] [DataField("size")] public int Size { get; private set; } = 1;
|
[ViewVariables] [DataField("size")] public int Size { get; private set; } = 1;
|
||||||
|
|
||||||
[ViewVariables] public int SizeUsed { get; private set; }
|
[ViewVariables] public int SizeUsed { get; private set; }
|
||||||
@@ -74,7 +89,7 @@ namespace Content.Shared.Body.Part
|
|||||||
// TODO BODY surgerydata
|
// TODO BODY surgerydata
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// What types of BodyParts this <see cref="IBodyPart"/> can easily attach to.
|
/// What types of BodyParts this <see cref="SharedBodyPartComponent"/> can easily attach to.
|
||||||
/// For the most part, most limbs aren't universal and require extra work to
|
/// For the most part, most limbs aren't universal and require extra work to
|
||||||
/// attach between types.
|
/// attach between types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -82,17 +97,14 @@ namespace Content.Shared.Body.Part
|
|||||||
[DataField("compatibility")]
|
[DataField("compatibility")]
|
||||||
public BodyPartCompatibility Compatibility { get; private set; } = BodyPartCompatibility.Universal;
|
public BodyPartCompatibility Compatibility { get; private set; } = BodyPartCompatibility.Universal;
|
||||||
|
|
||||||
/// <summary>
|
// TODO BODY Mechanisms occupying different parts at the body level
|
||||||
/// Set of all <see cref="IMechanism"/> currently inside this
|
|
||||||
/// <see cref="IBodyPart"/>.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IReadOnlyCollection<IMechanism> Mechanisms => _mechanisms;
|
public IReadOnlyCollection<SharedMechanismComponent> Mechanisms => _mechanisms;
|
||||||
|
|
||||||
// TODO BODY Replace with a simulation of organs
|
// TODO BODY Replace with a simulation of organs
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents if body part is vital for creature.
|
/// Whether or not the owning <see cref="Body"/> will die if all
|
||||||
/// If the last vital body part is removed creature dies
|
/// <see cref="SharedBodyPartComponent"/>s of this type are removed from it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
[DataField("vital")]
|
[DataField("vital")]
|
||||||
@@ -105,7 +117,7 @@ namespace Content.Shared.Body.Part
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public ISurgeryData? SurgeryDataComponent => Owner.GetComponentOrNull<ISurgeryData>();
|
public ISurgeryData? SurgeryDataComponent => Owner.GetComponentOrNull<ISurgeryData>();
|
||||||
|
|
||||||
protected virtual void OnAddMechanism(IMechanism mechanism)
|
protected virtual void OnAddMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
var prototypeId = mechanism.Owner.Prototype!.ID;
|
var prototypeId = mechanism.Owner.Prototype!.ID;
|
||||||
|
|
||||||
@@ -120,7 +132,7 @@ namespace Content.Shared.Body.Part
|
|||||||
Dirty();
|
Dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnRemoveMechanism(IMechanism mechanism)
|
protected virtual void OnRemoveMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
_mechanismIds.Remove(mechanism.Owner.Prototype!.ID);
|
_mechanismIds.Remove(mechanism.Owner.Prototype!.ID);
|
||||||
mechanism.Part = null;
|
mechanism.Part = null;
|
||||||
@@ -176,11 +188,6 @@ namespace Content.Shared.Body.Part
|
|||||||
return SurgeryDataComponent?.CheckSurgery(surgery) ?? false;
|
return SurgeryDataComponent?.CheckSurgery(surgery) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to perform surgery on this <see cref="IBodyPart"/> with the given
|
|
||||||
/// tool.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if successful, false if there was an error.</returns>
|
|
||||||
public bool AttemptSurgery(SurgeryType toolType, IBodyPartContainer target, ISurgeon surgeon, IEntity performer)
|
public bool AttemptSurgery(SurgeryType toolType, IBodyPartContainer target, ISurgeon surgeon, IEntity performer)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(toolType);
|
DebugTools.AssertNotNull(toolType);
|
||||||
@@ -191,14 +198,14 @@ namespace Content.Shared.Body.Part
|
|||||||
return SurgeryDataComponent?.PerformSurgery(toolType, target, surgeon, performer) ?? false;
|
return SurgeryDataComponent?.PerformSurgery(toolType, target, surgeon, performer) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanAttachPart(IBodyPart part)
|
public bool CanAttachPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(part);
|
DebugTools.AssertNotNull(part);
|
||||||
|
|
||||||
return SurgeryDataComponent?.CanAttachBodyPart(part) ?? false;
|
return SurgeryDataComponent?.CanAttachBodyPart(part) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool CanAddMechanism(IMechanism mechanism)
|
public virtual bool CanAddMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(mechanism);
|
DebugTools.AssertNotNull(mechanism);
|
||||||
|
|
||||||
@@ -208,19 +215,16 @@ namespace Content.Shared.Body.Part
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to add a mechanism onto this body part.
|
/// Tries to add a <see cref="SharedMechanismComponent"/> to this part.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mechanism">The mechanism to try to add.</param>
|
/// <param name="mechanism">The mechanism to add.</param>
|
||||||
/// <param name="force">
|
/// <param name="force">
|
||||||
/// Whether or not to check if the mechanism can be added.
|
/// Whether or not to check if the mechanism is compatible.
|
||||||
|
/// Passing true does not guarantee it to be added, for example if
|
||||||
|
/// it was already added before.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>
|
/// <returns>true if added, false otherwise even if it was already added.</returns>
|
||||||
/// True if successful, false if there was an error
|
public bool TryAddMechanism(SharedMechanismComponent mechanism, bool force = false)
|
||||||
/// (e.g. not enough room in <see cref="IBodyPart"/>).
|
|
||||||
/// Will return false even when forced if the mechanism is already
|
|
||||||
/// added in this <see cref="IBodyPart"/>.
|
|
||||||
/// </returns>
|
|
||||||
public bool TryAddMechanism(IMechanism mechanism, bool force = false)
|
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(mechanism);
|
DebugTools.AssertNotNull(mechanism);
|
||||||
|
|
||||||
@@ -239,7 +243,12 @@ namespace Content.Shared.Body.Part
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoveMechanism(IMechanism mechanism)
|
/// <summary>
|
||||||
|
/// Tries to remove the given <see cref="mechanism"/> from this part.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mechanism">The mechanism to remove.</param>
|
||||||
|
/// <returns>True if it was removed, false otherwise.</returns>
|
||||||
|
public bool RemoveMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(mechanism);
|
DebugTools.AssertNotNull(mechanism);
|
||||||
|
|
||||||
@@ -253,7 +262,14 @@ namespace Content.Shared.Body.Part
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoveMechanism(IMechanism mechanism, EntityCoordinates coordinates)
|
/// <summary>
|
||||||
|
/// Tries to remove the given <see cref="mechanism"/> from this
|
||||||
|
/// part and drops it at the specified coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mechanism">The mechanism to remove.</param>
|
||||||
|
/// <param name="coordinates">The coordinates to drop it at.</param>
|
||||||
|
/// <returns>True if it was removed, false otherwise.</returns>
|
||||||
|
public bool RemoveMechanism(SharedMechanismComponent mechanism, EntityCoordinates coordinates)
|
||||||
{
|
{
|
||||||
if (RemoveMechanism(mechanism))
|
if (RemoveMechanism(mechanism))
|
||||||
{
|
{
|
||||||
@@ -264,7 +280,16 @@ namespace Content.Shared.Body.Part
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DeleteMechanism(IMechanism mechanism)
|
/// <summary>
|
||||||
|
/// Tries to destroy the given <see cref="SharedMechanismComponent"/> from
|
||||||
|
/// this part.
|
||||||
|
/// The mechanism won't be deleted if it is not in this body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the mechanism was in this body part and destroyed,
|
||||||
|
/// false otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public bool DeleteMechanism(SharedMechanismComponent mechanism)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(mechanism);
|
DebugTools.AssertNotNull(mechanism);
|
||||||
|
|
||||||
@@ -277,7 +302,7 @@ namespace Content.Shared.Body.Part
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddedToBody(IBody body)
|
private void AddedToBody(SharedBodyComponent body)
|
||||||
{
|
{
|
||||||
Owner.Transform.LocalRotation = 0;
|
Owner.Transform.LocalRotation = 0;
|
||||||
Owner.Transform.AttachParent(body.Owner);
|
Owner.Transform.AttachParent(body.Owner);
|
||||||
@@ -289,7 +314,7 @@ namespace Content.Shared.Body.Part
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemovedFromBody(IBody old)
|
private void RemovedFromBody(SharedBodyComponent old)
|
||||||
{
|
{
|
||||||
if (!Owner.Transform.Deleted)
|
if (!Owner.Transform.Deleted)
|
||||||
{
|
{
|
||||||
@@ -304,10 +329,13 @@ namespace Content.Shared.Body.Part
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnAddedToBody(IBody body) { }
|
protected virtual void OnAddedToBody(SharedBodyComponent body) { }
|
||||||
|
|
||||||
protected virtual void OnRemovedFromBody(IBody old) { }
|
protected virtual void OnRemovedFromBody(SharedBodyComponent old) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gibs the body part.
|
||||||
|
/// </summary>
|
||||||
public virtual void Gib()
|
public virtual void Gib()
|
||||||
{
|
{
|
||||||
foreach (var mechanism in _mechanisms)
|
foreach (var mechanism in _mechanisms)
|
||||||
@@ -315,12 +343,44 @@ namespace Content.Shared.Body.Part
|
|||||||
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]
|
||||||
public class BodyPartComponentState : ComponentState
|
public class BodyPartComponentState : ComponentState
|
||||||
{
|
{
|
||||||
[NonSerialized] private List<IMechanism>? _mechanisms;
|
[NonSerialized] private List<SharedMechanismComponent>? _mechanisms;
|
||||||
|
|
||||||
public readonly EntityUid[] MechanismIds;
|
public readonly EntityUid[] MechanismIds;
|
||||||
|
|
||||||
@@ -329,7 +389,7 @@ namespace Content.Shared.Body.Part
|
|||||||
MechanismIds = mechanismIds;
|
MechanismIds = mechanismIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IMechanism> Mechanisms(IEntityManager? entityManager = null)
|
public List<SharedMechanismComponent> Mechanisms(IEntityManager? entityManager = null)
|
||||||
{
|
{
|
||||||
if (_mechanisms != null)
|
if (_mechanisms != null)
|
||||||
{
|
{
|
||||||
@@ -338,7 +398,7 @@ namespace Content.Shared.Body.Part
|
|||||||
|
|
||||||
entityManager ??= IoCManager.Resolve<IEntityManager>();
|
entityManager ??= IoCManager.Resolve<IEntityManager>();
|
||||||
|
|
||||||
var mechanisms = new List<IMechanism>(MechanismIds.Length);
|
var mechanisms = new List<SharedMechanismComponent>(MechanismIds.Length);
|
||||||
|
|
||||||
foreach (var id in MechanismIds)
|
foreach (var id in MechanismIds)
|
||||||
{
|
{
|
||||||
@@ -347,7 +407,7 @@ namespace Content.Shared.Body.Part
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entity.TryGetComponent(out IMechanism? mechanism))
|
if (!entity.TryGetComponent(out SharedMechanismComponent? mechanism))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ using Robust.Shared.ViewVariables;
|
|||||||
namespace Content.Shared.Body.Preset
|
namespace Content.Shared.Body.Preset
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the <see cref="IBodyPart"/>s used in a <see cref="IBody"/>.
|
/// Defines the parts used in a body.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Prototype("bodyPreset")]
|
[Prototype("bodyPreset")]
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Content.Shared.Body.Slot
|
|||||||
/// The part currently in this slot, if any.
|
/// The part currently in this slot, if any.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IBodyPart? Part { get; private set; }
|
public SharedBodyPartComponent? Part { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of slots that this slot connects to.
|
/// List of slots that this slot connects to.
|
||||||
@@ -45,21 +45,21 @@ namespace Content.Shared.Body.Slot
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public HashSet<BodyPartSlot> Connections { get; private set; }
|
public HashSet<BodyPartSlot> Connections { get; private set; }
|
||||||
|
|
||||||
public event Action<IBodyPart>? PartAdded;
|
public event Action<SharedBodyPartComponent>? PartAdded;
|
||||||
|
|
||||||
public event Action<IBodyPart>? PartRemoved;
|
public event Action<SharedBodyPartComponent>? PartRemoved;
|
||||||
|
|
||||||
internal void SetConnectionsInternal(IEnumerable<BodyPartSlot> connections)
|
internal void SetConnectionsInternal(IEnumerable<BodyPartSlot> connections)
|
||||||
{
|
{
|
||||||
Connections = new HashSet<BodyPartSlot>(connections);
|
Connections = new HashSet<BodyPartSlot>(connections);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanAddPart(IBodyPart part)
|
public bool CanAddPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
return Part == null && part.PartType == PartType;
|
return Part == null && part.PartType == PartType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryAddPart(IBodyPart part)
|
public bool TryAddPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
if (!CanAddPart(part))
|
if (!CanAddPart(part))
|
||||||
{
|
{
|
||||||
@@ -70,7 +70,7 @@ namespace Content.Shared.Body.Slot
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPart(IBodyPart part)
|
public void SetPart(SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
if (Part != null)
|
if (Part != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Content.Shared.Body.Surgery
|
|||||||
public interface ISurgeon
|
public interface ISurgeon
|
||||||
{
|
{
|
||||||
public delegate void MechanismRequestCallback(
|
public delegate void MechanismRequestCallback(
|
||||||
IMechanism target,
|
SharedMechanismComponent target,
|
||||||
IBodyPartContainer container,
|
IBodyPartContainer container,
|
||||||
ISurgeon surgeon,
|
ISurgeon surgeon,
|
||||||
IEntity performer);
|
IEntity performer);
|
||||||
@@ -25,10 +25,10 @@ namespace Content.Shared.Body.Surgery
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// When performing a surgery, the <see cref="SurgeryDataComponent"/>
|
/// When performing a surgery, the <see cref="SurgeryDataComponent"/>
|
||||||
/// may sometimes require selecting from a set of
|
/// may sometimes require selecting from a set of
|
||||||
/// <see cref="IMechanism"/>s to operate on.
|
/// <see cref="SharedMechanismComponent"/>s to operate on.
|
||||||
/// This function is called in that scenario, and it is expected that you call
|
/// This function is called in that scenario, and it is expected that you call
|
||||||
/// the callback with one <see cref="IMechanism"/> from the provided list.
|
/// the callback with one <see cref="SharedMechanismComponent"/> from the provided list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RequestMechanism(IEnumerable<IMechanism> options, MechanismRequestCallback callback);
|
public void RequestMechanism(IEnumerable<SharedMechanismComponent> options, MechanismRequestCallback callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,21 +6,21 @@ using Robust.Shared.GameObjects;
|
|||||||
namespace Content.Shared.Body.Surgery
|
namespace Content.Shared.Body.Surgery
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the current surgery state of a <see cref="IBodyPart"/>.
|
/// Represents the current surgery state of a <see cref="SharedBodyPartComponent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISurgeryData : IComponent
|
public interface ISurgeryData : IComponent
|
||||||
{
|
{
|
||||||
public delegate void SurgeryAction(IBodyPartContainer container, ISurgeon surgeon, IEntity performer);
|
public delegate void SurgeryAction(IBodyPartContainer container, ISurgeon surgeon, IEntity performer);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="IBodyPart"/> this
|
/// The <see cref="SharedBodyPartComponent"/> this
|
||||||
/// <see cref="ISurgeryData"/> is attached to.
|
/// <see cref="ISurgeryData"/> is attached to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBodyPart? Parent { get; }
|
public SharedBodyPartComponent? Parent { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="BodyPartType"/> of the parent
|
/// The <see cref="BodyPartType"/> of the parent
|
||||||
/// <see cref="IBodyPart"/>.
|
/// <see cref="SharedBodyPartComponent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BodyPartType? ParentType { get; }
|
public BodyPartType? ParentType { get; }
|
||||||
|
|
||||||
@@ -31,18 +31,18 @@ namespace Content.Shared.Body.Surgery
|
|||||||
public string GetDescription();
|
public string GetDescription();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns whether a <see cref="IMechanism"/> can be added into the
|
/// Returns whether a <see cref="SharedMechanismComponent"/> can be added into the
|
||||||
/// <see cref="IBodyPart"/> this <see cref="ISurgeryData"/>
|
/// <see cref="SharedBodyPartComponent"/> this <see cref="ISurgeryData"/>
|
||||||
/// represents.
|
/// represents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanAddMechanism(IMechanism mechanism);
|
public bool CanAddMechanism(SharedMechanismComponent mechanism);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns whether the given <see cref="IBodyPart"/> can be connected
|
/// Returns whether the given <see cref="SharedBodyPartComponent"/> can be connected
|
||||||
/// to the <see cref="IBodyPart"/> this <see cref="ISurgeryData"/>
|
/// to the <see cref="SharedBodyPartComponent"/> this <see cref="ISurgeryData"/>
|
||||||
/// represents.
|
/// represents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanAttachBodyPart(IBodyPart part);
|
public bool CanAttachBodyPart(SharedBodyPartComponent part);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the delegate corresponding to the surgery step using the given
|
/// Gets the delegate corresponding to the surgery step using the given
|
||||||
@@ -56,7 +56,7 @@ namespace Content.Shared.Body.Surgery
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns whether the given <see cref="SurgeryType"/> can be used to
|
/// Returns whether the given <see cref="SurgeryType"/> can be used to
|
||||||
/// perform a surgery on the <see cref="IBodyPart"/> this
|
/// perform a surgery on the <see cref="SharedBodyPartComponent"/> this
|
||||||
/// <see cref="ISurgeryData"/> represents.
|
/// <see cref="ISurgeryData"/> represents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CheckSurgery(SurgeryType toolType)
|
public bool CheckSurgery(SurgeryType toolType)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ using Robust.Shared.ViewVariables;
|
|||||||
namespace Content.Shared.Body.Template
|
namespace Content.Shared.Body.Template
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the layout of a <see cref="IBody"/>.
|
/// Defines the layout of a body.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Prototype("bodyTemplate")]
|
[Prototype("bodyTemplate")]
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Content.Shared.CharacterAppearance
|
|||||||
{
|
{
|
||||||
public static class HumanoidVisualLayersExtension
|
public static class HumanoidVisualLayersExtension
|
||||||
{
|
{
|
||||||
public static HumanoidVisualLayers? ToHumanoidLayer(this IBodyPart part)
|
public static HumanoidVisualLayers? ToHumanoidLayer(this SharedBodyPartComponent part)
|
||||||
{
|
{
|
||||||
return part.PartType switch
|
return part.PartType switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Content.Shared.Damage
|
|||||||
/// <see cref="SharedBodyComponent"/> may require it for extra data
|
/// <see cref="SharedBodyComponent"/> may require it for extra data
|
||||||
/// (such as selecting which limb to target).
|
/// (such as selecting which limb to target).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// TODO BODY: Remove and pretend it never existed
|
||||||
public class DamageChangeParams : EventArgs
|
public class DamageChangeParams : EventArgs
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ namespace Content.Shared.Disposal.Components
|
|||||||
|
|
||||||
// TODO: Probably just need a disposable tag.
|
// TODO: Probably just need a disposable tag.
|
||||||
if (!entity.TryGetComponent(out SharedItemComponent? storable) &&
|
if (!entity.TryGetComponent(out SharedItemComponent? storable) &&
|
||||||
!entity.HasComponent<IBody>())
|
!entity.HasComponent<SharedBodyComponent>())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace Content.Shared.MedicalScanner
|
|||||||
|
|
||||||
bool IDragDropOn.CanDragDropOn(DragDropEvent eventArgs)
|
bool IDragDropOn.CanDragDropOn(DragDropEvent eventArgs)
|
||||||
{
|
{
|
||||||
return eventArgs.Dragged.HasComponent<IBody>();
|
return eventArgs.Dragged.HasComponent<SharedBodyComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract bool DragDropOn(DragDropEvent eventArgs);
|
public abstract bool DragDropOn(DragDropEvent eventArgs);
|
||||||
|
|||||||
Reference in New Issue
Block a user