Add IngestionBlocker component (#5692)

This commit is contained in:
Leon Friedrich
2021-12-05 07:56:27 +13:00
committed by GitHub
parent e9e9a6871d
commit bfff21ea73
11 changed files with 169 additions and 152 deletions

View File

@@ -27,8 +27,6 @@ using System.Linq;
using Robust.Shared.Utility;
using Content.Server.Inventory.Components;
using Content.Shared.Inventory;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Tag;
namespace Content.Server.Nutrition.EntitySystems
{
@@ -55,6 +53,7 @@ namespace Content.Server.Nutrition.EntitySystems
SubscribeLocalEvent<FoodComponent, GetInteractionVerbsEvent>(AddEatVerb);
SubscribeLocalEvent<SharedBodyComponent, ForceFeedEvent>(OnForceFeed);
SubscribeLocalEvent<ForceFeedCancelledEvent>(OnForceFeedCancelled);
SubscribeLocalEvent<InventoryComponent, IngestionAttemptEvent>(OnInventoryIngestAttempt);
}
/// <summary>
@@ -139,13 +138,8 @@ namespace Content.Server.Nutrition.EntitySystems
!_bodySystem.TryGetComponentsOnMechanisms<StomachComponent>(userUid, out var stomachs, body))
return false;
if (IsMouthBlocked(userUid, out var blocker))
{
var name = EntityManager.GetComponent<MetaDataComponent>(blocker.Value).EntityName;
_popupSystem.PopupEntity(Loc.GetString("food-system-remove-mask", ("entity", name)),
userUid, Filter.Entities(userUid));
if (IsMouthBlocked(userUid, userUid))
return true;
}
var usedUtensils = new List<UtensilComponent>();
@@ -264,13 +258,8 @@ namespace Content.Server.Nutrition.EntitySystems
return true;
}
if (IsMouthBlocked(targetUid, out var blocker))
{
var name = EntityManager.GetComponent<MetaDataComponent>(blocker.Value).EntityName;
_popupSystem.PopupEntity(Loc.GetString("food-system-remove-mask", ("entity", name)),
userUid, Filter.Entities(userUid));
if (IsMouthBlocked(targetUid, userUid))
return true;
}
if (!TryGetRequiredUtensils(userUid, food, out var utensils))
return true;
@@ -364,7 +353,7 @@ namespace Content.Server.Nutrition.EntitySystems
if (!Resolve(uid, ref food) || !Resolve(target, ref body, false))
return;
if (IsMouthBlocked(target, out _))
if (IsMouthBlocked(target))
return;
if (!_solutionContainerSystem.TryGetSolution(uid, food.SolutionName, out var foodSolution))
@@ -448,62 +437,53 @@ namespace Content.Server.Nutrition.EntitySystems
}
/// <summary>
/// Is an entity's mouth accessible, or is it blocked by something like a mask? Does not actually check if
/// the user has a mouth. Body system when?
/// Block ingestion attempts based on the equipped mask or head-wear
/// </summary>
public bool IsMouthBlocked(EntityUid uid, [NotNullWhen(true)] out EntityUid? blockingEntity,
InventoryComponent? inventory = null)
private void OnInventoryIngestAttempt(EntityUid uid, InventoryComponent component, IngestionAttemptEvent args)
{
blockingEntity = null;
if (args.Cancelled)
return;
if (!Resolve(uid, ref inventory, false))
return false;
IngestionBlockerComponent blocker;
// check masks
if (inventory.TryGetSlotItem(EquipmentSlotDefines.Slots.MASK, out ItemComponent? mask))
if (component.TryGetSlotItem(EquipmentSlotDefines.Slots.MASK, out ItemComponent? mask) &&
EntityManager.TryGetComponent(mask.OwnerUid, out blocker) &&
blocker.Enabled)
{
// For now, lets just assume that any masks always covers the mouth
// TODO MASKS if the ability is added to raise/lower masks, this needs to be updated.
blockingEntity = mask.OwnerUid;
return true;
args.Blocker = mask.OwnerUid;
args.Cancel();
return;
}
// check helmets. Note that not all helmets cover the face.
if (inventory.TryGetSlotItem(EquipmentSlotDefines.Slots.HEAD, out ItemComponent? head) &&
EntityManager.TryGetComponent(head.OwnerUid, out TagComponent tag) &&
tag.HasTag("ConcealsFace"))
if (component.TryGetSlotItem(EquipmentSlotDefines.Slots.HEAD, out ItemComponent? head) &&
EntityManager.TryGetComponent(head.OwnerUid, out blocker) &&
blocker.Enabled)
{
blockingEntity = head.OwnerUid;
return true;
args.Blocker = head.OwnerUid;
args.Cancel();
}
}
/// <summary>
/// Check whether the target's mouth is blocked by equipment (masks or head-wear).
/// </summary>
/// <param name="uid">The target whose equipment is checked</param>
/// <param name="popupUid">Optional entity that will receive an informative pop-up identifying the blocking
/// piece of equipment.</param>
/// <returns></returns>
public bool IsMouthBlocked(EntityUid uid, EntityUid? popupUid = null)
{
var attempt = new IngestionAttemptEvent();
RaiseLocalEvent(uid, attempt, false);
if (attempt.Cancelled && attempt.Blocker != null && popupUid != null)
{
var name = EntityManager.GetComponent<MetaDataComponent>(attempt.Blocker.Value).EntityName;
_popupSystem.PopupEntity(Loc.GetString("food-system-remove-mask", ("entity", name)),
uid, Filter.Entities(popupUid.Value));
}
return false;
}
}
public sealed class ForceFeedEvent : EntityEventArgs
{
public readonly EntityUid User;
public readonly FoodComponent Food;
public readonly Solution FoodSolution;
public readonly List<UtensilComponent> Utensils;
public ForceFeedEvent(EntityUid user, FoodComponent food, Solution foodSolution, List<UtensilComponent> utensils)
{
User = user;
Food = food;
FoodSolution = foodSolution;
Utensils = utensils;
}
}
public sealed class ForceFeedCancelledEvent : EntityEventArgs
{
public readonly FoodComponent Food;
public ForceFeedCancelledEvent(FoodComponent food)
{
Food = food;
return attempt.Cancelled;
}
}
}