Make ItemCabinet use ItemSlots (#4771)
* pda slot names * cabinets use item slots * fix yaml * fix tests
This commit is contained in:
@@ -31,7 +31,7 @@ namespace Content.IntegrationTests.Tests.PDA
|
||||
components:
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
pda_id_slot:
|
||||
pdaIdSlot:
|
||||
whitelist:
|
||||
components:
|
||||
- IdCard
|
||||
@@ -79,7 +79,7 @@ namespace Content.IntegrationTests.Tests.PDA
|
||||
|
||||
var itemSlots = dummyPda.GetComponent<SharedItemSlotsComponent>();
|
||||
sEntityManager.EntitySysManager.GetEntitySystem<SharedItemSlotsSystem>()
|
||||
.TryInsertContent(itemSlots, pdaIdCard, PDAComponent.IDSlotName);
|
||||
.TryInsertContent(itemSlots, pdaIdCard, pdaComponent.IdSlot);
|
||||
var pdaContainedId = pdaComponent.ContainedID;
|
||||
|
||||
// The PDA in the hand should be found first
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Cabinet;
|
||||
using Content.Server.GameObjects.Components;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Whitelist;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Utility
|
||||
{
|
||||
@@ -30,14 +25,16 @@ namespace Content.IntegrationTests.Tests.Utility
|
||||
- type: entity
|
||||
id: WhitelistDummy
|
||||
components:
|
||||
- type: ItemCabinet
|
||||
whitelist:
|
||||
prototypes:
|
||||
- ValidPrototypeDummy
|
||||
components:
|
||||
- {ValidComponent}
|
||||
tags:
|
||||
- ValidTag
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
slotName:
|
||||
whitelist:
|
||||
prototypes:
|
||||
- ValidPrototypeDummy
|
||||
components:
|
||||
- {ValidComponent}
|
||||
tags:
|
||||
- ValidTag
|
||||
|
||||
- type: entity
|
||||
id: InvalidComponentDummy
|
||||
@@ -102,7 +99,7 @@ namespace Content.IntegrationTests.Tests.Utility
|
||||
|
||||
// Test from serialized
|
||||
var dummy = entityManager.SpawnEntity("WhitelistDummy", mapCoordinates);
|
||||
var whitelistSer = dummy.GetComponent<ItemCabinetComponent>().Whitelist;
|
||||
var whitelistSer = dummy.GetComponent<SharedItemSlotsComponent>().Slots.Values.First().Whitelist;
|
||||
Assert.That(whitelistSer, Is.Not.Null);
|
||||
|
||||
Assert.That(whitelistSer.Components, Is.Not.Null);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Content.Shared.Sound;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -8,8 +6,7 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Content.Server.Cabinet
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for entities that can hold one item that fits the whitelist, which can be extracted by interacting with
|
||||
/// the entity, and can have an item fitting the whitelist placed back inside
|
||||
/// Used for entities that can be opened, closed, and can hold one item. E.g., fire extinguisher cabinets.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class ItemCabinetComponent : Component
|
||||
@@ -24,21 +21,10 @@ namespace Content.Server.Cabinet
|
||||
public SoundSpecifier DoorSound { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The prototype that should be spawned inside the cabinet when it is map initialized.
|
||||
/// The slot name, used to get the actual item slot from the ItemSlotsComponent.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("spawnPrototype")]
|
||||
public string? SpawnPrototype { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A whitelist defining which entities are allowed into the cabinet.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("whitelist")]
|
||||
public EntityWhitelist? Whitelist = null;
|
||||
|
||||
[ViewVariables]
|
||||
public ContainerSlot ItemContainer = default!;
|
||||
[DataField("cabinetSlot")]
|
||||
public string CabinetSlot = "cabinetSlot";
|
||||
|
||||
/// <summary>
|
||||
/// Whether the cabinet is currently open or not.
|
||||
|
||||
@@ -1,52 +1,68 @@
|
||||
using Content.Server.Hands.Components;
|
||||
using Content.Server.Items;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.Cabinet;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Player;
|
||||
using System;
|
||||
|
||||
namespace Content.Server.Cabinet
|
||||
{
|
||||
public class ItemCabinetSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
||||
[Dependency] private readonly SharedItemSlotsSystem _itemSlotsSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ItemCabinetComponent, MapInitEvent>(OnMapInitialize);
|
||||
|
||||
SubscribeLocalEvent<ItemCabinetComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<ItemCabinetComponent, InteractHandEvent>(OnInteractHand);
|
||||
SubscribeLocalEvent<ItemCabinetComponent, ActivateInWorldEvent>(OnActivateInWorld);
|
||||
|
||||
SubscribeLocalEvent<ItemCabinetComponent, TryEjectItemCabinetEvent>(OnTryEjectItemCabinet);
|
||||
SubscribeLocalEvent<ItemCabinetComponent, TryInsertItemCabinetEvent>(OnTryInsertItemCabinet);
|
||||
SubscribeLocalEvent<ItemCabinetComponent, ToggleItemCabinetEvent>(OnToggleItemCabinet);
|
||||
|
||||
SubscribeLocalEvent<ItemCabinetComponent, GetInteractionVerbsEvent>(AddEjectInsertVerbs);
|
||||
SubscribeLocalEvent<ItemCabinetComponent, ComponentStartup>(InitializeAppearance);
|
||||
SubscribeLocalEvent<ItemCabinetComponent, ItemSlotChangedEvent>(OnItemSlotChanged);
|
||||
SubscribeLocalEvent<ItemCabinetComponent, GetActivationVerbsEvent>(AddToggleOpenVerb);
|
||||
}
|
||||
|
||||
private void AddToggleOpenVerb(EntityUid uid, ItemCabinetComponent component, GetActivationVerbsEvent args)
|
||||
private void InitializeAppearance(EntityUid uid, ItemCabinetComponent component, ComponentStartup args)
|
||||
{
|
||||
UpdateAppearance(uid, component);
|
||||
}
|
||||
|
||||
private void UpdateAppearance(EntityUid uid,
|
||||
ItemCabinetComponent? cabinet = null,
|
||||
SharedItemSlotsComponent? itemSlots = null,
|
||||
SharedAppearanceComponent? appearance = null)
|
||||
{
|
||||
if (!Resolve(uid, ref cabinet, ref itemSlots, ref appearance))
|
||||
return;
|
||||
|
||||
appearance.SetData(ItemCabinetVisuals.IsOpen, cabinet.Opened);
|
||||
|
||||
if (!itemSlots.Slots.TryGetValue(cabinet.CabinetSlot, out var slot))
|
||||
return;
|
||||
|
||||
appearance.SetData(ItemCabinetVisuals.ContainsItem, slot.HasEntity);
|
||||
}
|
||||
|
||||
private void OnItemSlotChanged(EntityUid uid, ItemCabinetComponent cabinet, ItemSlotChangedEvent args)
|
||||
{
|
||||
UpdateAppearance(uid, cabinet, args.SlotsComponent);
|
||||
}
|
||||
|
||||
private void AddToggleOpenVerb(EntityUid uid, ItemCabinetComponent cabinet, GetActivationVerbsEvent args)
|
||||
{
|
||||
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
|
||||
return;
|
||||
|
||||
// Toggle open verb
|
||||
Verb toggleVerb = new();
|
||||
toggleVerb.Act = () => OnToggleItemCabinet(uid, component);
|
||||
if (component.Opened)
|
||||
toggleVerb.Act = () => ToggleItemCabinet(uid, cabinet);
|
||||
if (cabinet.Opened)
|
||||
{
|
||||
toggleVerb.Text = Loc.GetString("verb-categories-close");
|
||||
toggleVerb.IconTexture = "/Textures/Interface/VerbIcons/close.svg.192dpi.png";
|
||||
@@ -59,210 +75,65 @@ namespace Content.Server.Cabinet
|
||||
args.Verbs.Add(toggleVerb);
|
||||
}
|
||||
|
||||
private void AddEjectInsertVerbs(EntityUid uid, ItemCabinetComponent component, GetInteractionVerbsEvent args)
|
||||
{
|
||||
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
|
||||
return;
|
||||
|
||||
// "Eject" item verb
|
||||
if (component.Opened &&
|
||||
component.ItemContainer.ContainedEntity != null &&
|
||||
_actionBlockerSystem.CanPickup(args.User))
|
||||
{
|
||||
Verb verb = new();
|
||||
verb.Act = () =>
|
||||
{
|
||||
TakeItem(component, args.Hands, component.ItemContainer.ContainedEntity, args.User);
|
||||
UpdateVisuals(component);
|
||||
};
|
||||
verb.Text = Loc.GetString("pick-up-verb-get-data-text");
|
||||
verb.IconTexture = "/Textures/Interface/VerbIcons/pickup.svg.192dpi.png";
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
// Insert item verb
|
||||
if (component.Opened &&
|
||||
args.Using != null &&
|
||||
_actionBlockerSystem.CanDrop(args.User) &&
|
||||
(component.Whitelist?.IsValid(args.Using) ?? true) &&
|
||||
component.ItemContainer.CanInsert(args.Using))
|
||||
{
|
||||
Verb verb = new();
|
||||
verb.Act = () =>
|
||||
{
|
||||
args.Hands.TryPutEntityIntoContainer(args.Using, component.ItemContainer);
|
||||
UpdateVisuals(component);
|
||||
};
|
||||
verb.Category = VerbCategory.Insert;
|
||||
verb.Text = args.Using.Name;
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMapInitialize(EntityUid uid, ItemCabinetComponent comp, MapInitEvent args)
|
||||
{
|
||||
var owner = EntityManager.GetEntity(uid);
|
||||
comp.ItemContainer =
|
||||
owner.EnsureContainer<ContainerSlot>("item_cabinet", out _);
|
||||
|
||||
if (comp.SpawnPrototype != null)
|
||||
comp.ItemContainer.Insert(EntityManager.SpawnEntity(comp.SpawnPrototype, owner.Transform.Coordinates));
|
||||
|
||||
UpdateVisuals(comp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try insert an item if the cabinet is opened. Otherwise, just try open it.
|
||||
/// </summary>
|
||||
private void OnInteractUsing(EntityUid uid, ItemCabinetComponent comp, InteractUsingEvent args)
|
||||
{
|
||||
args.Handled = true;
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (!comp.Opened)
|
||||
{
|
||||
RaiseLocalEvent(uid, new ToggleItemCabinetEvent(), false);
|
||||
}
|
||||
ToggleItemCabinet(uid, comp);
|
||||
else
|
||||
{
|
||||
RaiseLocalEvent(uid, new TryInsertItemCabinetEvent(args.User, args.Used), false);
|
||||
}
|
||||
_itemSlotsSystem.TryInsertContent(uid, args.Used, args.User);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the cabinet is opened and has an entity, try and take it. Otherwise toggle the cabinet open/closed;
|
||||
/// </summary>
|
||||
private void OnInteractHand(EntityUid uid, ItemCabinetComponent comp, InteractHandEvent args)
|
||||
{
|
||||
args.Handled = true;
|
||||
if (comp.Opened)
|
||||
{
|
||||
if (comp.ItemContainer.ContainedEntity == null)
|
||||
{
|
||||
RaiseLocalEvent(uid, new ToggleItemCabinetEvent(), false);
|
||||
return;
|
||||
}
|
||||
RaiseLocalEvent(uid, new TryEjectItemCabinetEvent(args.User), false);
|
||||
}
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (!EntityManager.TryGetComponent(uid, out SharedItemSlotsComponent itemSlots))
|
||||
return;
|
||||
|
||||
if (!itemSlots.Slots.TryGetValue(comp.CabinetSlot, out var slot))
|
||||
return;
|
||||
|
||||
if (comp.Opened && slot.HasEntity)
|
||||
_itemSlotsSystem.TryEjectContent(uid, comp.CabinetSlot, args.User);
|
||||
else
|
||||
{
|
||||
RaiseLocalEvent(uid, new ToggleItemCabinetEvent(), false);
|
||||
}
|
||||
ToggleItemCabinet(uid, comp);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnActivateInWorld(EntityUid uid, ItemCabinetComponent comp, ActivateInWorldEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
RaiseLocalEvent(uid, new ToggleItemCabinetEvent(), false);
|
||||
ToggleItemCabinet(uid, comp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the ItemCabinet's state.
|
||||
/// </summary>
|
||||
private void OnToggleItemCabinet(EntityUid uid, ItemCabinetComponent comp, ToggleItemCabinetEvent? args = null)
|
||||
private void ToggleItemCabinet(EntityUid uid, ItemCabinetComponent? cabinet = null)
|
||||
{
|
||||
comp.Opened = !comp.Opened;
|
||||
ClickLatchSound(comp);
|
||||
UpdateVisuals(comp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to insert an entity into the ItemCabinet's slot from the user's hands.
|
||||
/// </summary>
|
||||
private static void OnTryInsertItemCabinet(EntityUid uid, ItemCabinetComponent comp, TryInsertItemCabinetEvent args)
|
||||
{
|
||||
if (comp.ItemContainer.ContainedEntity != null || args.Cancelled || (comp.Whitelist != null && !comp.Whitelist.IsValid(args.Item)))
|
||||
{
|
||||
if (!Resolve(uid, ref cabinet))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.User.TryGetComponent<HandsComponent>(out var hands) || !hands.Drop(args.Item, comp.ItemContainer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
cabinet.Opened = !cabinet.Opened;
|
||||
SoundSystem.Play(Filter.Pvs(uid), cabinet.DoorSound.GetSound(), uid, AudioHelpers.WithVariation(0.15f));
|
||||
|
||||
UpdateVisuals(comp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to eject the ItemCabinet's item, either into the user's hands or onto the floor.
|
||||
/// </summary>
|
||||
private static void OnTryEjectItemCabinet(EntityUid uid, ItemCabinetComponent comp, TryEjectItemCabinetEvent args)
|
||||
{
|
||||
if (comp.ItemContainer.ContainedEntity == null || args.Cancelled)
|
||||
return;
|
||||
if (args.User.TryGetComponent(out SharedHandsComponent? hands))
|
||||
{
|
||||
// Put into hands
|
||||
TakeItem(comp, hands, comp.ItemContainer.ContainedEntity, args.User);
|
||||
}
|
||||
else if (comp.ItemContainer.Remove(comp.ItemContainer.ContainedEntity))
|
||||
{
|
||||
comp.ItemContainer.ContainedEntity.Transform.Coordinates = args.User.Transform.Coordinates;
|
||||
}
|
||||
UpdateVisuals(comp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to eject the ItemCabinet's item, either into the user's hands. Used by both <see
|
||||
/// cref="OnTryEjectItemCabinet"/> and the eject verbs.
|
||||
/// </summary>
|
||||
private static void TakeItem(ItemCabinetComponent comp, SharedHandsComponent hands, IEntity containedEntity, IEntity user)
|
||||
{
|
||||
if (containedEntity.HasComponent<ItemComponent>())
|
||||
{
|
||||
if (!hands.TryPutInActiveHandOrAny(containedEntity))
|
||||
containedEntity.Transform.Coordinates = hands.Owner.Transform.Coordinates;
|
||||
|
||||
comp.Owner.PopupMessage(user,
|
||||
Loc.GetString("comp-item-cabinet-successfully-taken",
|
||||
("item", containedEntity),
|
||||
("cabinet", comp.Owner)));
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateVisuals(ItemCabinetComponent comp)
|
||||
{
|
||||
if (comp.Owner.TryGetComponent(out SharedAppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(ItemCabinetVisuals.IsOpen, comp.Opened);
|
||||
appearance.SetData(ItemCabinetVisuals.ContainsItem, comp.ItemContainer.ContainedEntity != null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ClickLatchSound(ItemCabinetComponent comp)
|
||||
{
|
||||
SoundSystem.Play(Filter.Pvs(comp.Owner), comp.DoorSound.GetSound(), comp.Owner, AudioHelpers.WithVariation(0.15f));
|
||||
}
|
||||
}
|
||||
|
||||
public class ToggleItemCabinetEvent : EntityEventArgs
|
||||
{
|
||||
}
|
||||
|
||||
public class TryEjectItemCabinetEvent : CancellableEntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The user who tried to eject the item.
|
||||
/// </summary>
|
||||
public IEntity User;
|
||||
|
||||
public TryEjectItemCabinetEvent(IEntity user)
|
||||
{
|
||||
User = user;
|
||||
}
|
||||
}
|
||||
|
||||
public class TryInsertItemCabinetEvent : CancellableEntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The user who tried to eject the item.
|
||||
/// </summary>
|
||||
public IEntity User;
|
||||
|
||||
/// <summary>
|
||||
/// The item to be inserted.
|
||||
/// </summary>
|
||||
public IEntity Item;
|
||||
|
||||
public TryInsertItemCabinetEvent(IEntity user, IEntity item)
|
||||
{
|
||||
User = user;
|
||||
Item = item;
|
||||
UpdateAppearance(uid, cabinet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,11 @@ namespace Content.Server.PDA
|
||||
{
|
||||
public override string Name => "PDA";
|
||||
|
||||
public const string IDSlotName = "pda_id_slot";
|
||||
public const string PenSlotName = "pda_pen_slot";
|
||||
[DataField("idSlot")]
|
||||
public string IdSlot = "pdaIdSlot";
|
||||
|
||||
[DataField("penSlot")]
|
||||
public string PenSlot = "pdaPenSlot";
|
||||
|
||||
[ViewVariables] [DataField("idCard")] public string? StartingIdCard;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Content.Server.PDA
|
||||
SubscribeLocalEvent<PDAComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<PDAComponent, ActivateInWorldEvent>(OnActivateInWorld);
|
||||
SubscribeLocalEvent<PDAComponent, UseInHandEvent>(OnUse);
|
||||
SubscribeLocalEvent<PDAComponent, ItemSlotChanged>(OnItemSlotChanged);
|
||||
SubscribeLocalEvent<PDAComponent, ItemSlotChangedEvent>(OnItemSlotChanged);
|
||||
SubscribeLocalEvent<PDAComponent, LightToggleEvent>(OnLightToggle);
|
||||
|
||||
SubscribeLocalEvent<PDAComponent, UplinkInitEvent>(OnUplinkInit);
|
||||
@@ -53,7 +53,7 @@ namespace Content.Server.PDA
|
||||
// if pda prototype doesn't have slots, ID will drop down on ground
|
||||
var idCard = EntityManager.SpawnEntity(pda.StartingIdCard, pda.Owner.Transform.Coordinates);
|
||||
if (EntityManager.TryGetComponent(uid, out SharedItemSlotsComponent? itemSlots))
|
||||
_slotsSystem.TryInsertContent(itemSlots, idCard, PDAComponent.IDSlotName);
|
||||
_slotsSystem.TryInsertContent(itemSlots, idCard, pda.IdSlot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +71,10 @@ namespace Content.Server.PDA
|
||||
args.Handled = OpenUI(pda, args.User);
|
||||
}
|
||||
|
||||
private void OnItemSlotChanged(EntityUid uid, PDAComponent pda, ItemSlotChanged args)
|
||||
private void OnItemSlotChanged(EntityUid uid, PDAComponent pda, ItemSlotChangedEvent args)
|
||||
{
|
||||
// check if ID slot changed
|
||||
if (args.SlotName == PDAComponent.IDSlotName)
|
||||
if (args.SlotName == pda.IdSlot)
|
||||
{
|
||||
var item = args.ContainedItem;
|
||||
if (item == null || !EntityManager.TryGetComponent(item.Value, out IdCardComponent ? idCard))
|
||||
@@ -82,7 +82,7 @@ namespace Content.Server.PDA
|
||||
else
|
||||
pda.ContainedID = idCard;
|
||||
}
|
||||
else if (args.SlotName == PDAComponent.PenSlotName)
|
||||
else if (args.SlotName == pda.PenSlot)
|
||||
{
|
||||
var item = args.ContainedItem;
|
||||
pda.PenInserted = item != null;
|
||||
@@ -162,14 +162,12 @@ namespace Content.Server.PDA
|
||||
|
||||
case PDAEjectIDMessage _:
|
||||
{
|
||||
if (pda.Owner.TryGetComponent(out SharedItemSlotsComponent? itemSlots))
|
||||
_slotsSystem.TryEjectContent(itemSlots, PDAComponent.IDSlotName, msg.Session.AttachedEntity);
|
||||
_slotsSystem.TryEjectContent(pda.Owner.Uid, pda.IdSlot, msg.Session.AttachedEntity);
|
||||
break;
|
||||
}
|
||||
case PDAEjectPenMessage _:
|
||||
{
|
||||
if (pda.Owner.TryGetComponent(out SharedItemSlotsComponent? itemSlots))
|
||||
_slotsSystem.TryEjectContent(itemSlots, PDAComponent.PenSlotName, msg.Session.AttachedEntity);
|
||||
_slotsSystem.TryEjectContent(pda.Owner.Uid, pda.PenSlot, msg.Session.AttachedEntity);
|
||||
break;
|
||||
}
|
||||
case PDAShowUplinkMessage _:
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace Content.Server.Sandbox
|
||||
if (pda.Owner.TryGetComponent(out SharedItemSlotsComponent? itemSlots))
|
||||
{
|
||||
_entityManager.EntitySysManager.GetEntitySystem<SharedItemSlotsSystem>().
|
||||
TryInsertContent(itemSlots, newID, PDAComponent.IDSlotName);
|
||||
TryInsertContent(itemSlots, newID, pda.IdSlot);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -5,14 +5,14 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
/// <summary>
|
||||
/// Item was placed in or removed from one of the slots in <see cref="SharedItemSlotsComponent"/>
|
||||
/// </summary>
|
||||
public class ItemSlotChanged : EntityEventArgs
|
||||
public class ItemSlotChangedEvent : EntityEventArgs
|
||||
{
|
||||
public SharedItemSlotsComponent SlotsComponent;
|
||||
public string SlotName;
|
||||
public ItemSlot Slot;
|
||||
public readonly EntityUid? ContainedItem;
|
||||
|
||||
public ItemSlotChanged(SharedItemSlotsComponent slotsComponent, string slotName, ItemSlot slot)
|
||||
public ItemSlotChangedEvent(SharedItemSlotsComponent slotsComponent, string slotName, ItemSlot slot)
|
||||
{
|
||||
SlotsComponent = slotsComponent;
|
||||
SlotName = slotName;
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Shared.Sound;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
@@ -31,9 +32,23 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
[ViewVariables] [DataField("insertSound")] public SoundSpecifier? InsertSound;
|
||||
[ViewVariables] [DataField("ejectSound")] public SoundSpecifier? EjectSound;
|
||||
|
||||
/// <summary>
|
||||
/// The name of this item slot. This will be shown to the user in the verb menu.
|
||||
/// </summary>
|
||||
[ViewVariables] public string Name
|
||||
{
|
||||
get => _name != string.Empty
|
||||
? Loc.GetString(_name)
|
||||
: ContainerSlot.ContainedEntity?.Name ?? string.Empty;
|
||||
set => _name = value;
|
||||
}
|
||||
[DataField("name")] private string _name = string.Empty;
|
||||
|
||||
[DataField("item", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
[ViewVariables] public string? StartingItem;
|
||||
|
||||
[ViewVariables] public ContainerSlot ContainerSlot = default!;
|
||||
|
||||
public bool HasEntity => ContainerSlot.ContainedEntity != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
var item = EntityManager.SpawnEntity(slot.StartingItem, itemSlots.Owner.Transform.Coordinates);
|
||||
slot.ContainerSlot.Insert(item);
|
||||
|
||||
RaiseLocalEvent(uid, new ItemSlotChanged(itemSlots, slotName, slot));
|
||||
RaiseLocalEvent(uid, new ItemSlotChangedEvent(itemSlots, slotName, slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,11 +76,9 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
continue;
|
||||
|
||||
Verb verb = new();
|
||||
// TODO ITEMSLOTS give item slot names localization strings?
|
||||
// Basically: its much nicer to have "insert ID" instead of the much longer "Eject <full-in-game-username>'s ID card (assistant)"
|
||||
verb.Text = slot.ContainerSlot.ContainedEntity.Name;
|
||||
verb.Text = slot.Name;
|
||||
verb.Category = VerbCategory.Eject;
|
||||
verb.Act = () => TryEjectContent(component, slotName, args.User);
|
||||
verb.Act = () => TryEjectContent(uid, slotName, args.User, component);
|
||||
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
@@ -100,9 +98,7 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
continue;
|
||||
|
||||
Verb verb = new();
|
||||
// TODO ITEMSLOTS give item slot names localization strings?
|
||||
// Basically: its much nicer to have "insert ID" instead of the much longer "Insert <full-in-game-username>'s ID card (assistant)"
|
||||
verb.Text = args.Using.Name;
|
||||
verb.Text = slot.Name != string.Empty ? slot.Name : args.Using.Name;
|
||||
verb.Category = VerbCategory.Insert;
|
||||
verb.Act = () => InsertContent(component, slot, slotName, args.Using);
|
||||
args.Verbs.Add(verb);
|
||||
@@ -114,15 +110,18 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = TryInsertContent(itemSlots, args.Used, args.User);
|
||||
args.Handled = TryInsertContent(uid, args.Used, args.User, itemSlots);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to insert or swap an item in any fitting item slot from users hand. If a valid slot already contains an item, it will swap it out.
|
||||
/// </summary>
|
||||
/// <returns>False if failed to insert item</returns>
|
||||
public bool TryInsertContent(SharedItemSlotsComponent itemSlots, IEntity item, IEntity user, SharedHandsComponent? hands = null)
|
||||
public bool TryInsertContent(EntityUid uid, IEntity item, IEntity user, SharedItemSlotsComponent? itemSlots = null, SharedHandsComponent? hands = null)
|
||||
{
|
||||
if (!Resolve(uid, ref itemSlots))
|
||||
return false;
|
||||
|
||||
if (!Resolve(user.Uid, ref hands))
|
||||
{
|
||||
itemSlots.Owner.PopupMessage(user, Loc.GetString("item-slots-try-insert-no-hands"));
|
||||
@@ -164,7 +163,7 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
{
|
||||
// insert item
|
||||
slot.ContainerSlot.Insert(item);
|
||||
RaiseLocalEvent(itemSlots.Owner.Uid, new ItemSlotChanged(itemSlots, slotName, slot));
|
||||
RaiseLocalEvent(itemSlots.Owner.Uid, new ItemSlotChangedEvent(itemSlots, slotName, slot));
|
||||
|
||||
// play sound
|
||||
if (slot.InsertSound != null)
|
||||
@@ -218,8 +217,11 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
/// <summary>
|
||||
/// Try to eject item from slot to users hands
|
||||
/// </summary>
|
||||
public bool TryEjectContent(SharedItemSlotsComponent itemSlots, string slotName, IEntity? user)
|
||||
public bool TryEjectContent(EntityUid uid, string slotName, IEntity? user, SharedItemSlotsComponent? itemSlots = null)
|
||||
{
|
||||
if (!Resolve(uid, ref itemSlots))
|
||||
return false;
|
||||
|
||||
if (!itemSlots.Slots.TryGetValue(slotName, out var slot))
|
||||
return false;
|
||||
|
||||
@@ -246,7 +248,7 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
if (slot.EjectSound != null)
|
||||
SoundSystem.Play(Filter.Pvs(itemSlots.Owner), slot.EjectSound.GetSound(), itemSlots.Owner);
|
||||
|
||||
RaiseLocalEvent(itemSlots.Owner.Uid, new ItemSlotChanged(itemSlots, slotName, slot));
|
||||
RaiseLocalEvent(itemSlots.Owner.Uid, new ItemSlotChangedEvent(itemSlots, slotName, slot));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
### Used for item cabinet (fire extinguisher cabinets)
|
||||
|
||||
## Displayed when the item is successfully taken out of the cabinet.
|
||||
|
||||
comp-item-cabinet-successfully-taken = You take { THE($item) } from { THE($cabinet) }.
|
||||
@@ -35,12 +35,13 @@
|
||||
type: UplinkBoundUserInterface
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
pda_pen_slot:
|
||||
pdaPenSlot:
|
||||
item: "Pen"
|
||||
whitelist:
|
||||
tags:
|
||||
- Write
|
||||
pda_id_slot:
|
||||
pdaIdSlot:
|
||||
name: ID Card
|
||||
insertSound:
|
||||
path: /Audio/Weapons/Guns/MagIn/batrifle_magin.ogg
|
||||
ejectSound:
|
||||
|
||||
@@ -20,14 +20,17 @@
|
||||
- type: ItemCabinet
|
||||
doorSound:
|
||||
path: /Audio/Machines/machine_switch.ogg
|
||||
whitelist:
|
||||
components:
|
||||
- FireExtinguisher
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: ItemCabinetVisualizer
|
||||
openState: open
|
||||
closedState: closed
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cabinetSlot:
|
||||
whitelist:
|
||||
components:
|
||||
- FireExtinguisher
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
|
||||
@@ -44,8 +47,15 @@
|
||||
parent: ExtinguisherCabinet
|
||||
suffix: Filled
|
||||
components:
|
||||
- type: ItemCabinet
|
||||
spawnPrototype: FireExtinguisher
|
||||
- type: ItemCabinet
|
||||
spawnPrototype: FireExtinguisher
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cabinetSlot:
|
||||
item: FireExtinguisher
|
||||
whitelist:
|
||||
components:
|
||||
- FireExtinguisher
|
||||
|
||||
- type: entity
|
||||
id: ExtinguisherCabinetFilledOpen
|
||||
|
||||
@@ -18,14 +18,17 @@
|
||||
- type: ItemCabinet
|
||||
doorSound:
|
||||
path: /Audio/Machines/machine_switch.ogg
|
||||
whitelist:
|
||||
tags:
|
||||
- FireAxe
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: ItemCabinetVisualizer
|
||||
closedState: glass
|
||||
openState: glass-up
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cabinetSlot:
|
||||
whitelist:
|
||||
tags:
|
||||
- FireAxe
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
|
||||
@@ -42,8 +45,14 @@
|
||||
parent: FireAxeCabinet
|
||||
suffix: Filled
|
||||
components:
|
||||
- type: ItemCabinet
|
||||
spawnPrototype: FireAxe
|
||||
- type: ItemCabinet
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cabinetSlot:
|
||||
item: FireAxe
|
||||
whitelist:
|
||||
tags:
|
||||
- FireAxe
|
||||
|
||||
- type: entity
|
||||
id: FireAxeCabinetFilledOpen
|
||||
|
||||
Reference in New Issue
Block a user