Add IMechanism interface to body system (#1997)

This commit is contained in:
DrSmugleaf
2020-09-02 01:16:13 +02:00
committed by GitHub
parent 072f374bcc
commit 682b6b9568
9 changed files with 162 additions and 117 deletions

View File

@@ -36,7 +36,7 @@ namespace Content.Server.Body
{ {
private IBodyManagerComponent? _body; private IBodyManagerComponent? _body;
private readonly HashSet<Mechanism> _mechanisms = new HashSet<Mechanism>(); private readonly HashSet<IMechanism> _mechanisms = new HashSet<IMechanism>();
public BodyPart(BodyPartPrototype data) public BodyPart(BodyPartPrototype data)
{ {
@@ -146,11 +146,11 @@ namespace Content.Server.Body
public BodyPartCompatibility Compatibility { get; private set; } public BodyPartCompatibility Compatibility { get; private set; }
/// <summary> /// <summary>
/// Set of all <see cref="Mechanism"/> currently inside this /// Set of all <see cref="IMechanism"/> currently inside this
/// <see cref="IBodyPart"/>. /// <see cref="IBodyPart"/>.
/// </summary> /// </summary>
[ViewVariables] [ViewVariables]
public IReadOnlyCollection<Mechanism> Mechanisms => _mechanisms; public IReadOnlyCollection<IMechanism> Mechanisms => _mechanisms;
/// <summary> /// <summary>
/// This method is called by /// This method is called by
@@ -258,7 +258,7 @@ namespace Content.Server.Body
return SurgeryData.CanAttachBodyPart(part); return SurgeryData.CanAttachBodyPart(part);
} }
public bool CanInstallMechanism(Mechanism mechanism) public bool CanInstallMechanism(IMechanism mechanism)
{ {
return SizeUsed + mechanism.Size <= Size && return SizeUsed + mechanism.Size <= Size &&
SurgeryData.CanInstallMechanism(mechanism); SurgeryData.CanInstallMechanism(mechanism);
@@ -275,7 +275,7 @@ namespace Content.Server.Body
/// True if successful, false if there was an error /// True if successful, false if there was an error
/// (e.g. not enough room in <see cref="IBodyPart"/>). /// (e.g. not enough room in <see cref="IBodyPart"/>).
/// </returns> /// </returns>
private bool TryInstallMechanism(Mechanism mechanism) private bool TryInstallMechanism(IMechanism mechanism)
{ {
if (!CanInstallMechanism(mechanism)) if (!CanInstallMechanism(mechanism))
{ {
@@ -308,7 +308,7 @@ namespace Content.Server.Body
return true; return true;
} }
public bool TryDropMechanism(IEntity dropLocation, Mechanism mechanismTarget, public bool TryDropMechanism(IEntity dropLocation, IMechanism mechanismTarget,
[NotNullWhen(true)] out DroppedMechanismComponent dropped) [NotNullWhen(true)] out DroppedMechanismComponent dropped)
{ {
dropped = null!; dropped = null!;
@@ -331,16 +331,16 @@ namespace Content.Server.Body
} }
/// <summary> /// <summary>
/// Tries to destroy the given <see cref="Mechanism"/> in this /// Tries to destroy the given <see cref="IMechanism"/> in this
/// <see cref="IBodyPart"/>. Does NOT spawn a dropped entity. /// <see cref="IBodyPart"/>. Does NOT spawn a dropped entity.
/// </summary> /// </summary>
/// <summary> /// <summary>
/// Tries to destroy the given <see cref="Mechanism"/> in this /// Tries to destroy the given <see cref="IMechanism"/> in this
/// <see cref="IBodyPart"/>. /// <see cref="IBodyPart"/>.
/// </summary> /// </summary>
/// <param name="mechanismTarget">The mechanism to destroy.</param> /// <param name="mechanismTarget">The mechanism to destroy.</param>
/// <returns>True if successful, false otherwise.</returns> /// <returns>True if successful, false otherwise.</returns>
public bool DestroyMechanism(Mechanism mechanismTarget) public bool DestroyMechanism(IMechanism mechanismTarget)
{ {
if (!RemoveMechanism(mechanismTarget)) if (!RemoveMechanism(mechanismTarget))
{ {
@@ -365,7 +365,7 @@ namespace Content.Server.Body
return SurgeryData.PerformSurgery(toolType, target, surgeon, performer); return SurgeryData.PerformSurgery(toolType, target, surgeon, performer);
} }
private void AddMechanism(Mechanism mechanism) private void AddMechanism(IMechanism mechanism)
{ {
DebugTools.AssertNotNull(mechanism); DebugTools.AssertNotNull(mechanism);
@@ -402,7 +402,7 @@ namespace Content.Server.Body
/// </summary> /// </summary>
/// <param name="mechanism">The mechanism to remove.</param> /// <param name="mechanism">The mechanism to remove.</param>
/// <returns>True if it was removed, false otherwise.</returns> /// <returns>True if it was removed, false otherwise.</returns>
private bool RemoveMechanism(Mechanism mechanism) private bool RemoveMechanism(IMechanism mechanism)
{ {
DebugTools.AssertNotNull(mechanism); DebugTools.AssertNotNull(mechanism);

View File

@@ -54,12 +54,12 @@ namespace Content.Server.Body
int CurrentDurability { get; } int CurrentDurability { get; }
/// <summary> /// <summary>
/// Collection of all <see cref="Mechanism"/>s currently inside this /// Collection of all <see cref="IMechanism"/>s currently inside this
/// <see cref="IBodyPart"/>. /// <see cref="IBodyPart"/>.
/// To add and remove from this list see <see cref="AddMechanism"/> and /// To add and remove from this list see <see cref="AddMechanism"/> and
/// <see cref="RemoveMechanism"/> /// <see cref="RemoveMechanism"/>
/// </summary> /// </summary>
IReadOnlyCollection<Mechanism> Mechanisms { get; } IReadOnlyCollection<IMechanism> Mechanisms { get; }
/// <summary> /// <summary>
/// Path to the RSI that represents this <see cref="IBodyPart"/>. /// Path to the RSI that represents this <see cref="IBodyPart"/>.
@@ -109,23 +109,23 @@ namespace Content.Server.Body
bool CanAttachPart(IBodyPart part); bool CanAttachPart(IBodyPart part);
/// <summary> /// <summary>
/// Checks if a <see cref="Mechanism"/> can be installed on this /// Checks if a <see cref="IMechanism"/> can be installed on this
/// <see cref="IBodyPart"/>. /// <see cref="IBodyPart"/>.
/// </summary> /// </summary>
/// <returns>True if it can be installed, false otherwise.</returns> /// <returns>True if it can be installed, false otherwise.</returns>
bool CanInstallMechanism(Mechanism mechanism); bool CanInstallMechanism(IMechanism mechanism);
/// <summary> /// <summary>
/// Tries to remove the given <see cref="Mechanism"/> reference from /// Tries to remove the given <see cref="IMechanism"/> reference from
/// this <see cref="IBodyPart"/>. /// this <see cref="IBodyPart"/>.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The newly spawned <see cref="DroppedMechanismComponent"/>, or null /// The newly spawned <see cref="DroppedMechanismComponent"/>, or null
/// if there was an error in spawning the entity or removing the mechanism. /// if there was an error in spawning the entity or removing the mechanism.
/// </returns> /// </returns>
bool TryDropMechanism(IEntity dropLocation, Mechanism mechanismTarget, bool TryDropMechanism(IEntity dropLocation, IMechanism mechanismTarget,
[NotNullWhen(true)] out DroppedMechanismComponent dropped); [NotNullWhen(true)] out DroppedMechanismComponent dropped);
bool DestroyMechanism(Mechanism mechanism); bool DestroyMechanism(IMechanism mechanism);
} }
} }

View File

@@ -0,0 +1,103 @@
#nullable enable
using System.Collections.Generic;
using Content.Server.Body.Mechanisms.Behaviors;
using Content.Server.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Body;
namespace Content.Server.Body.Mechanisms
{
public interface IMechanism
{
string Id { get; }
string Name { get; set; }
/// <summary>
/// Professional description of the <see cref="IMechanism"/>.
/// </summary>
string Description { get; set; }
/// <summary>
/// The message to display upon examining a mob with this Mechanism installed.
/// If the string is empty (""), no message will be displayed.
/// </summary>
string ExamineMessage { get; set; }
// TODO: Make RSI properties sane
/// <summary>
/// Path to the RSI that represents this <see cref="IMechanism"/>.
/// </summary>
string RSIPath { get; set; }
/// <summary>
/// RSI state that represents this <see cref="IMechanism"/>.
/// </summary>
string RSIState { get; set; }
/// <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: 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; }
IReadOnlyList<MechanismBehavior> Behaviors { get; }
IBodyManagerComponent? Body { get; }
IBodyPart? Part { get; set; }
void EnsureInitialize();
void InstalledIntoBody();
void RemovedFromBody(IBodyManagerComponent old);
/// <summary>
/// This method is called by <see cref="IBodyPart.PreMetabolism"/> before
/// <see cref="MetabolismComponent.Update"/> is called.
/// </summary>
void PreMetabolism(float frameTime);
/// <summary>
/// This method is called by <see cref="IBodyPart.PostMetabolism"/> after
/// <see cref="MetabolismComponent.Update"/> is called.
/// </summary>
void PostMetabolism(float frameTime);
void AddBehavior(MechanismBehavior behavior);
/// <summary>
/// Removes a behavior from this mechanism.
/// </summary>
/// <param name="behavior">The behavior to remove.</param>
/// <returns>True if it was removed, false otherwise.</returns>
bool RemoveBehavior(MechanismBehavior behavior);
}
}

View File

@@ -16,7 +16,7 @@ namespace Content.Server.Body.Mechanisms
/// This includes livers, eyes, cameras, brains, explosive implants, /// This includes livers, eyes, cameras, brains, explosive implants,
/// binary communicators, and other things. /// binary communicators, and other things.
/// </summary> /// </summary>
public class Mechanism public class Mechanism : IMechanism
{ {
private IBodyPart? _part; private IBodyPart? _part;
@@ -29,7 +29,7 @@ namespace Content.Server.Body.Mechanisms
ExamineMessage = null!; ExamineMessage = null!;
RSIPath = null!; RSIPath = null!;
RSIState = null!; RSIState = null!;
Behaviors = new List<MechanismBehavior>(); _behaviors = new List<MechanismBehavior>();
} }
[ViewVariables] private bool Initialized { get; set; } [ViewVariables] private bool Initialized { get; set; }
@@ -40,74 +40,29 @@ namespace Content.Server.Body.Mechanisms
[ViewVariables] public string Name { get; set; } [ViewVariables] public string Name { get; set; }
/// <summary> [ViewVariables] public string Description { get; set; }
/// Professional description of the <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public string Description { get; set; }
/// <summary> [ViewVariables] public string ExamineMessage { get; set; }
/// The message to display upon examining a mob with this Mechanism installed.
/// If the string is empty (""), no message will be displayed.
/// </summary>
[ViewVariables]
public string ExamineMessage { get; set; }
/// <summary> [ViewVariables] public string RSIPath { get; set; }
/// Path to the RSI that represents this <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public string RSIPath { get; set; }
/// <summary> [ViewVariables] public string RSIState { get; set; }
/// RSI state that represents this <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public string RSIState { get; set; }
/// <summary> [ViewVariables] public int MaxDurability { get; set; }
/// Max HP of this <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public int MaxDurability { get; set; }
/// <summary> [ViewVariables] public int CurrentDurability { get; set; }
/// Current HP of this <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public int CurrentDurability { get; set; }
/// <summary> [ViewVariables] public int DestroyThreshold { get; set; }
/// At what HP this <see cref="Mechanism"/> is completely destroyed.
/// </summary>
[ViewVariables]
public int DestroyThreshold { get; set; }
/// <summary> [ViewVariables] public int Resistance { get; set; }
/// Armor of this <see cref="Mechanism"/> against attacks.
/// </summary>
[ViewVariables]
public int Resistance { get; set; }
/// <summary> [ViewVariables] public int Size { get; set; }
/// Determines a handful of things - mostly whether this
/// <see cref="Mechanism"/> can fit into a <see cref="IBodyPart"/>.
/// </summary>
[ViewVariables]
public int Size { get; set; }
/// <summary> [ViewVariables] public BodyPartCompatibility Compatibility { get; set; }
/// What kind of <see cref="IBodyPart"/> this <see cref="Mechanism"/> can be
/// easily installed into.
/// </summary>
[ViewVariables]
public BodyPartCompatibility Compatibility { get; set; }
/// <summary> private readonly List<MechanismBehavior> _behaviors;
/// The behaviors that this <see cref="Mechanism"/> performs.
/// </summary> [ViewVariables] public IReadOnlyList<MechanismBehavior> Behaviors => _behaviors;
[ViewVariables]
private List<MechanismBehavior> Behaviors { get; }
public IBodyManagerComponent? Body => Part?.Body; public IBodyManagerComponent? Body => Part?.Body;
@@ -167,7 +122,7 @@ namespace Content.Server.Body.Mechanisms
Size = data.Size; Size = data.Size;
Compatibility = data.Compatibility; Compatibility = data.Compatibility;
foreach (var behavior in Behaviors.ToArray()) foreach (var behavior in _behaviors.ToArray())
{ {
RemoveBehavior(behavior); RemoveBehavior(behavior);
} }
@@ -210,10 +165,6 @@ namespace Content.Server.Body.Mechanisms
} }
} }
/// <summary>
/// This method is called by <see cref="IBodyPart.PreMetabolism"/> before
/// <see cref="MetabolismComponent.Update"/> is called.
/// </summary>
public void PreMetabolism(float frameTime) public void PreMetabolism(float frameTime)
{ {
foreach (var behavior in Behaviors) foreach (var behavior in Behaviors)
@@ -222,10 +173,6 @@ namespace Content.Server.Body.Mechanisms
} }
} }
/// <summary>
/// This method is called by <see cref="IBodyPart.PostMetabolism"/> after
/// <see cref="MetabolismComponent.Update"/> is called.
/// </summary>
public void PostMetabolism(float frameTime) public void PostMetabolism(float frameTime)
{ {
foreach (var behavior in Behaviors) foreach (var behavior in Behaviors)
@@ -234,16 +181,21 @@ namespace Content.Server.Body.Mechanisms
} }
} }
private void AddBehavior(MechanismBehavior behavior) public void AddBehavior(MechanismBehavior behavior)
{ {
Behaviors.Add(behavior); _behaviors.Add(behavior);
behavior.Initialize(this); behavior.Initialize(this);
} }
private bool RemoveBehavior(MechanismBehavior behavior) public bool RemoveBehavior(MechanismBehavior behavior)
{ {
behavior.Remove(); if (_behaviors.Remove(behavior))
return Behaviors.Remove(behavior); {
behavior.Remove();
return true;
}
return false;
} }
} }
} }

View File

@@ -17,7 +17,7 @@ namespace Content.Server.Body.Surgery
[UsedImplicitly] [UsedImplicitly]
public class BiologicalSurgeryData : SurgeryData public class BiologicalSurgeryData : SurgeryData
{ {
private readonly List<Mechanism> _disconnectedOrgans = new List<Mechanism>(); private readonly List<IMechanism> _disconnectedOrgans = new List<IMechanism>();
private bool _skinOpened; private bool _skinOpened;
private bool _skinRetracted; private bool _skinRetracted;
@@ -118,7 +118,7 @@ namespace Content.Server.Body.Surgery
return toReturn; return toReturn;
} }
public override bool CanInstallMechanism(Mechanism mechanism) public override bool CanInstallMechanism(IMechanism mechanism)
{ {
return _skinOpened && _vesselsClamped && _skinRetracted; return _skinOpened && _vesselsClamped && _skinRetracted;
} }
@@ -170,7 +170,7 @@ namespace Content.Server.Body.Surgery
return; return;
} }
var toSend = new List<Mechanism>(); var toSend = new List<IMechanism>();
foreach (var mechanism in Parent.Mechanisms) foreach (var mechanism in Parent.Mechanisms)
{ {
if (!_disconnectedOrgans.Contains(mechanism)) if (!_disconnectedOrgans.Contains(mechanism))
@@ -185,7 +185,7 @@ namespace Content.Server.Body.Surgery
} }
} }
private void LoosenOrganSurgeryCallback(Mechanism target, IBodyPartContainer container, ISurgeon surgeon, private void LoosenOrganSurgeryCallback(IMechanism target, IBodyPartContainer container, ISurgeon surgeon,
IEntity performer) IEntity performer)
{ {
if (target == null || !Parent.Mechanisms.Contains(target)) if (target == null || !Parent.Mechanisms.Contains(target))
@@ -216,7 +216,7 @@ namespace Content.Server.Body.Surgery
} }
} }
private void RemoveOrganSurgeryCallback(Mechanism target, IBodyPartContainer container, ISurgeon surgeon, private void RemoveOrganSurgeryCallback(IMechanism target, IBodyPartContainer container, ISurgeon surgeon,
IEntity performer) IEntity performer)
{ {
if (target == null || !Parent.Mechanisms.Contains(target)) if (target == null || !Parent.Mechanisms.Contains(target))

View File

@@ -13,7 +13,7 @@ namespace Content.Server.Body.Surgery
public interface ISurgeon public interface ISurgeon
{ {
public delegate void MechanismRequestCallback( public delegate void MechanismRequestCallback(
Mechanism target, IMechanism target,
IBodyPartContainer container, IBodyPartContainer container,
ISurgeon surgeon, ISurgeon surgeon,
IEntity performer); IEntity performer);
@@ -29,6 +29,6 @@ namespace Content.Server.Body.Surgery
/// This function is called in that scenario, and it is expected that you call the callback with one mechanism from the /// This function is called in that scenario, and it is expected that you call the callback with one mechanism from the
/// provided list. /// provided list.
/// </summary> /// </summary>
public void RequestMechanism(IEnumerable<Mechanism> options, MechanismRequestCallback callback); public void RequestMechanism(IEnumerable<IMechanism> options, MechanismRequestCallback callback);
} }
} }

View File

@@ -38,10 +38,10 @@ namespace Content.Server.Body.Surgery
public abstract string GetDescription(IEntity target); public abstract string GetDescription(IEntity target);
/// <summary> /// <summary>
/// Returns whether a <see cref="Mechanism"/> can be installed into the /// Returns whether a <see cref="IMechanism"/> can be installed into the
/// <see cref="IBodyPart"/> this <see cref="SurgeryData"/> represents. /// <see cref="IBodyPart"/> this <see cref="SurgeryData"/> represents.
/// </summary> /// </summary>
public abstract bool CanInstallMechanism(Mechanism mechanism); public abstract bool CanInstallMechanism(IMechanism mechanism);
/// <summary> /// <summary>
/// Returns whether the given <see cref="IBodyPart"/> can be connected to the /// Returns whether the given <see cref="IBodyPart"/> can be connected to the

View File

@@ -40,7 +40,7 @@ namespace Content.Server.GameObjects.Components.Body
private IEntity? _performerCache; private IEntity? _performerCache;
[ViewVariables] public Mechanism ContainedMechanism { get; private set; } = default!; [ViewVariables] public IMechanism ContainedMechanism { get; private set; } = default!;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(GenericSurgeryUiKey.Key); [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(GenericSurgeryUiKey.Key);
@@ -81,7 +81,7 @@ namespace Content.Server.GameObjects.Components.Body
} }
} }
public void InitializeDroppedMechanism(Mechanism data) public void InitializeDroppedMechanism(IMechanism data)
{ {
ContainedMechanism = data; ContainedMechanism = data;
Owner.Name = Loc.GetString(ContainedMechanism.Name); Owner.Name = Loc.GetString(ContainedMechanism.Name);

View File

@@ -128,7 +128,7 @@ namespace Content.Server.GameObjects.Components.Body
public float BaseOperationTime { get => _baseOperateTime; set => _baseOperateTime = value; } public float BaseOperationTime { get => _baseOperateTime; set => _baseOperateTime = value; }
public void RequestMechanism(IEnumerable<Mechanism> options, ISurgeon.MechanismRequestCallback callback) public void RequestMechanism(IEnumerable<IMechanism> 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)
@@ -230,7 +230,7 @@ namespace Content.Server.GameObjects.Components.Body
/// <summary> /// <summary>
/// Called after the client chooses from a list of possible /// Called after the client chooses from a list of possible
/// <see cref="Mechanism"/> to choose from. /// <see cref="IMechanism"/> to choose from.
/// </summary> /// </summary>
private void HandleReceiveMechanism(int key) private void HandleReceiveMechanism(int key)
{ {
@@ -251,23 +251,13 @@ namespace Content.Server.GameObjects.Components.Body
private void SendNoUsefulWayToUsePopup() private void SendNoUsefulWayToUsePopup()
{ {
if (_bodyManagerComponentCache == null) _bodyManagerComponentCache?.Owner.PopupMessage(_performerCache,
{
return;
}
_bodyManagerComponentCache.Owner.PopupMessage(_performerCache,
Loc.GetString("You see no useful way to use {0:theName}.", Owner)); Loc.GetString("You see no useful way to use {0:theName}.", Owner));
} }
private void SendNoUsefulWayToUseAnymorePopup() private void SendNoUsefulWayToUseAnymorePopup()
{ {
if (_bodyManagerComponentCache == null) _bodyManagerComponentCache?.Owner.PopupMessage(_performerCache,
{
return;
}
_bodyManagerComponentCache.Owner.PopupMessage(_performerCache,
Loc.GetString("You see no useful way to use {0:theName} anymore.", Owner)); Loc.GetString("You see no useful way to use {0:theName} anymore.", Owner));
} }