get that crap outta here (completely rewrites inventorysystem) (#5807)

* some work

* equip: done
unequip: todo

* unequipping done & refactored events

* workin

* movin

* reee namespaces

* stun

* mobstate

* fixes

* some work on events

* removes serverside itemcomp & misc fixes

* work

* smol merge fix

* ports template to prototype & finishes ui

* moves relay & adds containerenumerator

* actions & cuffs

* my god what is actioncode

* more fixes

* im loosing my grasp on reality

* more fixes

* more work

* explosions

* yes

* more work

* more fixes

* merge master & misc fixed because i forgot to commit before merging master

* more fixes

* fixes

* moar

* more work

* moar fixes

* suffixmap

* more work on client

* motivation low

* no. no containers

* mirroring client to server

* fixes

* move serverinvcomp

* serverinventorycomponent is dead

* gaming

* only strippable & ai left...

* only ai and richtext left

* fixes ai

* fixes

* fixes sprite layers

* more fixes

* resolves optional

* yes

* stable™️

* fixes

* moar fixes

* moar

* fix some tests

* lmao

* no comment

* good to merge™️

* fixes build but for real

* adresses some reviews

* adresses some more reviews

* nullables, yo

* fixes lobbyscreen

* timid refactor to differentiate actor & target

* adresses more reviews

* more

* my god what a mess

* removed the rest of duplicates

* removed duplicate slotflags and renamed shoes to feet

* removes another unused one

* yes

* fixes lobby & makes tryunequip return unequipped item

* fixes

* some funny renames

* fixes

* misc improvements to attemptevents

* fixes

* merge fixes

Co-authored-by: Paul Ritter <ritter.paul1@gmail.com>
This commit is contained in:
Paul Ritter
2021-12-30 22:56:10 +01:00
committed by GitHub
parent 7a5adb47a1
commit 512d6a38c3
199 changed files with 2493 additions and 3300 deletions

View File

@@ -4,6 +4,7 @@ using Content.Client.Stylesheets;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Actions.Components; using Content.Shared.Actions.Components;
using Content.Shared.Actions.Prototypes; using Content.Shared.Actions.Prototypes;
using Content.Shared.Inventory;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
@@ -231,7 +232,7 @@ namespace Content.Client.Actions.UI
{ {
ActionPrototype actionPrototype => new ActionAttempt(actionPrototype), ActionPrototype actionPrototype => new ActionAttempt(actionPrototype),
ItemActionPrototype itemActionPrototype => ItemActionPrototype itemActionPrototype =>
(Item != null && IoCManager.Resolve<IEntityManager>().TryGetComponent<ItemActionsComponent?>(Item, out var itemActions)) ? Item.HasValue && IoCManager.Resolve<IEntityManager>().TryGetComponent<ItemActionsComponent?>(Item, out var itemActions) ?
new ItemActionAttempt(itemActionPrototype, Item.Value, itemActions) : null, new ItemActionAttempt(itemActionPrototype, Item.Value, itemActions) : null,
_ => null _ => null
}; };

View File

@@ -1,14 +1,7 @@
using Content.Client.Inventory;
using Content.Client.Items.Components; using Content.Client.Items.Components;
using Content.Shared.Clothing;
using Content.Shared.Inventory;
using Content.Shared.Item; using Content.Shared.Item;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -20,85 +13,11 @@ namespace Content.Client.Clothing
[NetworkedComponent()] [NetworkedComponent()]
public class ClothingComponent : ItemComponent public class ClothingComponent : ItemComponent
{ {
[DataField("femaleMask")]
private FemaleClothingMask _femaleMask = FemaleClothingMask.UniformFull;
public override string Name => "Clothing"; public override string Name => "Clothing";
private string? _clothingEquippedPrefix;
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField("ClothingPrefix")] [DataField("femaleMask")]
public string? ClothingEquippedPrefix public FemaleClothingMask FemaleMask { get; } = FemaleClothingMask.UniformFull;
{
get => _clothingEquippedPrefix;
set
{
if (_clothingEquippedPrefix == value)
return;
_clothingEquippedPrefix = value;
if(!Initialized) return;
if (!Owner.TryGetContainer(out IContainer? container))
return;
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(container.Owner, out ClientInventoryComponent? inventory))
return;
if (!inventory.TryFindItemSlots(Owner, out EquipmentSlotDefines.Slots? slots))
return;
inventory.SetSlotVisuals(slots.Value, Owner);
}
}
protected override void Initialize()
{
base.Initialize();
ClothingEquippedPrefix = ClothingEquippedPrefix;
}
[ViewVariables(VVAccess.ReadWrite)]
public FemaleClothingMask FemaleMask
{
get => _femaleMask;
set => _femaleMask = value;
}
public (RSI rsi, RSI.StateId stateId)? GetEquippedStateInfo(EquipmentSlotDefines.SlotFlags slot, string? speciesId=null)
{
if (RsiPath == null)
return null;
var rsi = IoCManager.Resolve<IResourceCache>().GetResource<RSIResource>(SharedSpriteComponent.TextureRoot / RsiPath).RSI;
var prefix = ClothingEquippedPrefix ?? EquippedPrefix;
var stateId = prefix != null ? $"{prefix}-equipped-{slot}" : $"equipped-{slot}";
if (speciesId != null)
{
var speciesState = $"{stateId}-{speciesId}";
if (rsi.TryGetState(speciesState, out _))
{
return (rsi, speciesState);
}
}
if (rsi.TryGetState(stateId, out _))
{
return (rsi, stateId);
}
return null;
}
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
if (curState is not ClothingComponentState state)
{
return;
}
ClothingEquippedPrefix = state.ClothingEquippedPrefix;
EquippedPrefix = state.EquippedPrefix;
}
} }
public enum FemaleClothingMask : byte public enum FemaleClothingMask : byte

View File

@@ -0,0 +1,162 @@
using System.Collections.Generic;
using Content.Client.Inventory;
using Content.Shared.CharacterAppearance;
using Content.Shared.Clothing;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
namespace Content.Client.Clothing;
public class ClothingSystem : EntitySystem
{
/// <summary>
/// This is a shitty hotfix written by me (Paul) to save me from renaming all files.
/// For some context, im currently refactoring inventory. Part of that is slots not being indexed by a massive enum anymore, but by strings.
/// Problem here: Every rsi-state is using the old enum-names in their state. I already used the new inventoryslots ALOT. tldr: its this or another week of renaming files.
/// </summary>
private static readonly Dictionary<string, string> TemporarySlotMap = new()
{
{"head", "HELMET"},
{"eyes", "EYES"},
{"ears", "EARS"},
{"mask", "MASK"},
{"outerClothing", "OUTERCLOTHING"},
{"jumpsuit", "INNERCLOTHING"},
{"neck", "NECK"},
{"back", "BACKPACK"},
{"belt", "BELT"},
{"gloves", "HAND"},
{"shoes", "FEET"},
{"id", "IDCARD"},
{"pocket1", "POCKET1"},
{"pocket2", "POCKET2"},
};
[Dependency] private IResourceCache _cache = default!;
[Dependency] private InventorySystem _inventorySystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ClothingComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<SpriteComponent, DidUnequipEvent>(OnDidUnequip);
}
private void OnDidUnequip(EntityUid uid, SpriteComponent component, DidUnequipEvent args)
{
component.LayerSetVisible(args.Slot, false);
}
public void InitClothing(EntityUid uid, ClientInventoryComponent? component = null, SpriteComponent? sprite = null)
{
if (!_inventorySystem.TryGetSlots(uid, out var slots, component) || !Resolve(uid, ref sprite, ref component)) return;
foreach (var slot in slots)
{
sprite.LayerMapReserveBlank(slot.Name);
if (!_inventorySystem.TryGetSlotContainer(uid, slot.Name, out var containerSlot, out _, component) ||
!containerSlot.ContainedEntity.HasValue) continue;
RenderEquipment(uid, containerSlot.ContainedEntity.Value, slot.Name, component, sprite);
}
}
private void OnGotEquipped(EntityUid uid, ClothingComponent component, GotEquippedEvent args)
{
if (!TryComp<SpriteComponent>(args.Equipee, out var sprite) || !TryComp<ClientInventoryComponent>(args.Equipee, out var invComp))
{
return;
}
var data = GetEquippedStateInfo(args.Equipment, args.Slot, invComp.SpeciesId, component);
if (data != null)
{
var (rsi, state) = data.Value;
sprite.LayerSetVisible(args.Slot, true);
sprite.LayerSetState(args.Slot, state, rsi);
sprite.LayerSetAutoAnimated(args.Slot, true);
if (args.Slot == "jumpsuit" && sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out _))
{
sprite.LayerSetState(HumanoidVisualLayers.StencilMask, component.FemaleMask switch
{
FemaleClothingMask.NoMask => "female_none",
FemaleClothingMask.UniformTop => "female_top",
_ => "female_full",
});
}
return;
}
sprite.LayerSetVisible(args.Slot, false);
}
private void RenderEquipment(EntityUid uid, EntityUid equipment, string slot,
ClientInventoryComponent? inventoryComponent = null, SpriteComponent? sprite = null, ClothingComponent? clothingComponent = null)
{
if(!Resolve(uid, ref inventoryComponent, ref sprite))
return;
if (!Resolve(equipment, ref clothingComponent, false))
{
sprite.LayerSetVisible(slot, false);
return;
}
var data = GetEquippedStateInfo(equipment, slot, inventoryComponent.SpeciesId, clothingComponent);
if (data == null) return;
var (rsi, state) = data.Value;
sprite.LayerSetVisible(slot, true);
sprite.LayerSetState(slot, state, rsi);
sprite.LayerSetAutoAnimated(slot, true);
if (slot == "jumpsuit" && sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out _))
{
sprite.LayerSetState(HumanoidVisualLayers.StencilMask, clothingComponent.FemaleMask switch
{
FemaleClothingMask.NoMask => "female_none",
FemaleClothingMask.UniformTop => "female_top",
_ => "female_full",
});
}
}
public (RSI rsi, RSI.StateId stateId)? GetEquippedStateInfo(EntityUid uid, string slot, string? speciesId=null, ClothingComponent? component = null)
{
if (!Resolve(uid, ref component))
return null;
if (component.RsiPath == null)
return null;
var rsi = _cache.GetResource<RSIResource>(SharedSpriteComponent.TextureRoot / component.RsiPath).RSI;
var correctedSlot = slot;
TemporarySlotMap.TryGetValue(correctedSlot, out correctedSlot);
var stateId = component.EquippedPrefix != null ? $"{component.EquippedPrefix}-equipped-{correctedSlot}" : $"equipped-{correctedSlot}";
if (speciesId != null)
{
var speciesState = $"{stateId}-{speciesId}";
if (rsi.TryGetState(speciesState, out _))
{
return (rsi, speciesState);
}
}
if (rsi.TryGetState(stateId, out _))
{
return (rsi, stateId);
}
return null;
}
}

View File

@@ -57,7 +57,6 @@ namespace Content.Client.Entry
"MagicMirror", "MagicMirror",
"FloorTile", "FloorTile",
"ShuttleController", "ShuttleController",
"HumanInventoryController",
"RandomInsulation", "RandomInsulation",
"Electrified", "Electrified",
"Electrocution", "Electrocution",

View File

@@ -1,4 +1,5 @@
using Content.Client.Items.UI; using Content.Client.HUD;
using Content.Client.Items.UI;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
@@ -10,7 +11,7 @@ namespace Content.Client.Hands
private bool _activeHand; private bool _activeHand;
private bool _highlighted; private bool _highlighted;
public HandButton(Texture texture, Texture storageTexture, string textureName, Texture blockedTexture, HandLocation location) : base(texture, storageTexture, textureName) public HandButton(int size, string textureName, string storageTextureName, IGameHud gameHud, Texture blockedTexture, HandLocation location) : base(size, textureName, storageTextureName, gameHud)
{ {
Location = location; Location = location;

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Content.Client.HUD; using Content.Client.HUD;
using Content.Client.Inventory;
using Content.Client.Items.Managers; using Content.Client.Items.Managers;
using Content.Client.Items.UI; using Content.Client.Items.UI;
using Content.Client.Resources; using Content.Client.Resources;
@@ -32,7 +33,7 @@ namespace Content.Client.Hands
private readonly HandsSystem _handsSystem; private readonly HandsSystem _handsSystem;
private readonly HandsComponent _handsComponent; private readonly HandsComponent _handsComponent;
private Texture StorageTexture => _gameHud.GetHudTexture("back.png"); private string StorageTexture => "back.png";
private Texture BlockedTexture => _resourceCache.GetTexture("/Textures/Interface/Inventory/blocked.png"); private Texture BlockedTexture => _resourceCache.GetTexture("/Textures/Interface/Inventory/blocked.png");
private ItemStatusPanel StatusPanel { get; } private ItemStatusPanel StatusPanel { get; }
@@ -166,9 +167,8 @@ namespace Content.Client.Hands
HandLocation.Right => "hand_r.png", HandLocation.Right => "hand_r.png",
_ => "hand_l.png" _ => "hand_l.png"
}; };
var buttonTexture = _gameHud.GetHudTexture(buttonTextureName);
return new HandButton(buttonTexture, StorageTexture, buttonTextureName, BlockedTexture, buttonLocation); return new HandButton(ClientInventorySystem.ButtonSize, buttonTextureName, StorageTexture, _gameHud, BlockedTexture, buttonLocation);
} }
private void UpdateHudTheme(int idx) private void UpdateHudTheme(int idx)

View File

@@ -1,17 +1,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using Content.Client.Items.UI;
using System.Linq;
using Content.Client.Clothing;
using Content.Shared.CharacterAppearance;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Movement.EntitySystems; using Robust.Client.UserInterface;
using Robust.Client.GameObjects; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using static Content.Shared.Inventory.EquipmentSlotDefines;
using static Content.Shared.Inventory.SharedInventoryComponent.ClientInventoryMessage;
namespace Content.Client.Inventory namespace Content.Client.Inventory
{ {
@@ -19,242 +15,21 @@ namespace Content.Client.Inventory
/// A character UI which shows items the user has equipped within his inventory /// A character UI which shows items the user has equipped within his inventory
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(SharedInventoryComponent))] [ComponentReference(typeof(InventoryComponent))]
public class ClientInventoryComponent : SharedInventoryComponent [Friend(typeof(ClientInventorySystem))]
public class ClientInventoryComponent : InventoryComponent
{ {
[Dependency] private readonly IEntityManager _entMan = default!; public Control BottomLeftButtons = default!;
public Control BottomRightButtons = default!;
public Control TopQuickButtons = default!;
private readonly Dictionary<Slots, EntityUid> _slots = new(); public SS14Window InventoryWindow = default!;
public IReadOnlyDictionary<Slots, EntityUid> AllSlots => _slots; public readonly Dictionary<string, List<ItemSlotButton>> SlotButtons = new();
[ViewVariables] public InventoryInterfaceController InterfaceController { get; private set; } = default!;
[ComponentDependency]
private ISpriteComponent? _sprite;
private bool _playerAttached = false;
[ViewVariables] [ViewVariables]
[DataField("speciesId")] public string? SpeciesId { get; set; } [DataField("speciesId")] public string? SpeciesId { get; set; }
protected override void OnRemove() public bool AttachedToGameHud;
{
base.OnRemove();
if (_playerAttached)
{
InterfaceController?.PlayerDetached();
}
InterfaceController?.Dispose();
}
protected override void Initialize()
{
base.Initialize();
var controllerType = ReflectionManager.LooseGetType(InventoryInstance.InterfaceControllerTypeName);
var args = new object[] {this};
InterfaceController = DynamicTypeFactory.CreateInstance<InventoryInterfaceController>(controllerType, args);
InterfaceController.Initialize();
if (_sprite != null)
{
foreach (var mask in InventoryInstance.SlotMasks.OrderBy(s => InventoryInstance.SlotDrawingOrder(s)))
{
if (mask == Slots.NONE)
{
continue;
}
_sprite.LayerMapReserveBlank(mask);
}
}
// Component state already came in but we couldn't set anything visually because, well, we didn't initialize yet.
foreach (var (slot, entity) in _slots)
{
_setSlot(slot, entity);
}
}
public override bool IsEquipped(EntityUid item)
{
return item != default && _slots.Values.Any(e => e == item);
}
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
base.HandleComponentState(curState, nextState);
if (curState is not InventoryComponentState state)
return;
var doneSlots = new HashSet<Slots>();
foreach (var (slot, entity) in state.Entities)
{
if (!_entMan.EntityExists(entity))
{
continue;
}
if (!_slots.ContainsKey(slot) || _slots[slot] != entity)
{
_slots[slot] = entity;
_setSlot(slot, entity);
}
doneSlots.Add(slot);
}
if (state.HoverEntity != null)
{
var (slot, (entity, fits)) = state.HoverEntity.Value;
InterfaceController?.HoverInSlot(slot, entity, fits);
}
foreach (var slot in _slots.Keys.ToList())
{
if (!doneSlots.Contains(slot))
{
_clearSlot(slot);
_slots.Remove(slot);
}
}
EntitySystem.Get<MovementSpeedModifierSystem>().RefreshMovementSpeedModifiers(Owner);
}
private void _setSlot(Slots slot, EntityUid entity)
{
SetSlotVisuals(slot, entity);
InterfaceController?.AddToSlot(slot, entity);
}
internal void SetSlotVisuals(Slots slot, EntityUid entity)
{
if (_sprite == null)
{
return;
}
if (_entMan.TryGetComponent(entity, out ClothingComponent? clothing))
{
var flag = SlotMasks[slot];
var data = clothing.GetEquippedStateInfo(flag, SpeciesId);
if (data != null)
{
var (rsi, state) = data.Value;
_sprite.LayerSetVisible(slot, true);
_sprite.LayerSetState(slot, state, rsi);
_sprite.LayerSetAutoAnimated(slot, true);
if (slot == Slots.INNERCLOTHING && _sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out _))
{
_sprite.LayerSetState(HumanoidVisualLayers.StencilMask, clothing.FemaleMask switch
{
FemaleClothingMask.NoMask => "female_none",
FemaleClothingMask.UniformTop => "female_top",
_ => "female_full",
});
}
return;
}
}
_sprite.LayerSetVisible(slot, false);
}
internal void ClearAllSlotVisuals()
{
if (_sprite == null)
return;
foreach (var slot in InventoryInstance.SlotMasks)
{
if (slot != Slots.NONE)
{
_sprite.LayerSetVisible(slot, false);
}
}
}
private void _clearSlot(Slots slot)
{
InterfaceController?.RemoveFromSlot(slot);
_sprite?.LayerSetVisible(slot, false);
}
public void SendEquipMessage(Slots slot)
{
var equipMessage = new ClientInventoryMessage(slot, ClientInventoryUpdate.Equip);
#pragma warning disable 618
SendNetworkMessage(equipMessage);
#pragma warning restore 618
}
public void SendUseMessage(Slots slot)
{
var equipmessage = new ClientInventoryMessage(slot, ClientInventoryUpdate.Use);
#pragma warning disable 618
SendNetworkMessage(equipmessage);
#pragma warning restore 618
}
public void SendHoverMessage(Slots slot)
{
#pragma warning disable 618
SendNetworkMessage(new ClientInventoryMessage(slot, ClientInventoryUpdate.Hover));
#pragma warning restore 618
}
public void SendOpenStorageUIMessage(Slots slot)
{
#pragma warning disable 618
SendNetworkMessage(new OpenSlotStorageUIMessage(slot));
#pragma warning restore 618
}
public void PlayerDetached()
{
InterfaceController.PlayerDetached();
_playerAttached = false;
}
public void PlayerAttached()
{
InterfaceController.PlayerAttached();
_playerAttached = true;
}
public override bool TryGetSlot(Slots slot, [NotNullWhen(true)] out EntityUid? item)
{
// dict TryGetValue uses default EntityUid, not null.
if (!_slots.ContainsKey(slot))
{
item = null;
return false;
}
item = _slots[slot];
return item != null;
}
public bool TryFindItemSlots(EntityUid item, [NotNullWhen(true)] out Slots? slots)
{
slots = null;
foreach (var (slot, entity) in _slots)
{
if (entity == item)
{
slots = slot;
return true;
}
}
return false;
}
} }
} }

View File

@@ -1,20 +1,52 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Content.Client.Clothing;
using Content.Client.HUD; using Content.Client.HUD;
using Content.Shared.Input; using Content.Shared.Input;
using Content.Client.Items.Managers;
using Content.Client.Items.UI;
using Content.Shared.CCVar;
using Content.Shared.Hands.Components;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Movement.EntitySystems; using Content.Shared.Inventory.Events;
using Content.Shared.Slippery; using Content.Shared.Item;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.Input.Binding; using Robust.Shared.Input.Binding;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
namespace Content.Client.Inventory namespace Content.Client.Inventory
{ {
[UsedImplicitly] [UsedImplicitly]
public sealed class ClientInventorySystem : EntitySystem public sealed class ClientInventorySystem : InventorySystem
{ {
[Dependency] private readonly IGameHud _gameHud = default!; [Dependency] private readonly IGameHud _gameHud = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IConfigurationManager _config = default!;
[Dependency] private readonly IItemSlotManager _itemSlotManager = default!;
[Dependency] private readonly ClothingSystem _clothingSystem = default!;
public const int ButtonSize = 64;
private const int ButtonSeparation = 4;
private const int RightSeparation = 2;
/// <summary>
/// Stores delegates used to create controls for a given <see cref="InventoryTemplatePrototype"/>.
/// </summary>
private readonly
Dictionary<string, Func<EntityUid, Dictionary<string, List<ItemSlotButton>>, (SS14Window window, Control bottomLeft, Control bottomRight, Control
topQuick)>>
_uiGenerateDelegates = new();
public override void Initialize() public override void Initialize()
{ {
@@ -25,29 +57,96 @@ namespace Content.Client.Inventory
InputCmdHandler.FromDelegate(_ => HandleOpenInventoryMenu())) InputCmdHandler.FromDelegate(_ => HandleOpenInventoryMenu()))
.Register<ClientInventorySystem>(); .Register<ClientInventorySystem>();
SubscribeLocalEvent<ClientInventoryComponent, PlayerAttachedEvent>((_, component, _) => component.PlayerAttached()); SubscribeLocalEvent<ClientInventoryComponent, PlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<ClientInventoryComponent, PlayerDetachedEvent>((_, component, _) => component.PlayerDetached()); SubscribeLocalEvent<ClientInventoryComponent, PlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<ClientInventoryComponent, SlipAttemptEvent>(OnSlipAttemptEvent); SubscribeLocalEvent<ClientInventoryComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<ClientInventoryComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed); SubscribeLocalEvent<ClientInventoryComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<ClientInventoryComponent, DidEquipEvent>(OnDidEquip);
SubscribeLocalEvent<ClientInventoryComponent, DidUnequipEvent>(OnDidUnequip);
_config.OnValueChanged(CCVars.HudTheme, UpdateHudTheme);
} }
// jesus christ, this is duplicated to server/client, should really just be shared.. public override bool TryEquip(EntityUid actor, EntityUid target, EntityUid itemUid, string slot, bool silent = false, bool force = false,
private void OnSlipAttemptEvent(EntityUid uid, ClientInventoryComponent component, SlipAttemptEvent args) InventoryComponent? inventory = null, SharedItemComponent? item = null)
{ {
if (component.TryGetSlot(EquipmentSlotDefines.Slots.SHOES, out EntityUid? shoes)) if(!target.IsClientSide() && !actor.IsClientSide() && !itemUid.IsClientSide()) RaiseNetworkEvent(new TryEquipNetworkMessage(actor, target, itemUid, slot, silent, force));
return base.TryEquip(actor, target, itemUid, slot, silent, force, inventory, item);
}
public override bool TryUnequip(EntityUid actor, EntityUid target, string slot, [NotNullWhen(true)] out EntityUid? removedItem, bool silent = false, bool force = false,
InventoryComponent? inventory = null)
{
if(!target.IsClientSide() && !actor.IsClientSide()) RaiseNetworkEvent(new TryUnequipNetworkMessage(actor, target, slot, silent, force));
return base.TryUnequip(actor, target, slot, out removedItem, silent, force, inventory);
}
private void OnDidUnequip(EntityUid uid, ClientInventoryComponent component, DidUnequipEvent args)
{
if (component.SlotButtons.TryGetValue(args.Slot, out var buttons))
{ {
RaiseLocalEvent(shoes.Value, args, false); foreach (var button in buttons)
{
_itemSlotManager.SetItemSlot(button, null);
}
} }
} }
private void OnRefreshMovespeed(EntityUid uid, ClientInventoryComponent component, RefreshMovementSpeedModifiersEvent args) private void OnDidEquip(EntityUid uid, ClientInventoryComponent component, DidEquipEvent args)
{ {
foreach (var (_, ent) in component.AllSlots) if (component.SlotButtons.TryGetValue(args.Slot, out var buttons))
{ {
if (ent != default) foreach (var button in buttons)
{ {
RaiseLocalEvent(ent, args, false); _itemSlotManager.SetItemSlot(button, args.Equipment);
}
}
}
private void OnPlayerDetached(EntityUid uid, ClientInventoryComponent component, PlayerDetachedEvent? args = null)
{
if(!component.AttachedToGameHud) return;
_gameHud.InventoryButtonVisible = false;
_gameHud.BottomLeftInventoryQuickButtonContainer.RemoveChild(component.BottomLeftButtons);
_gameHud.BottomRightInventoryQuickButtonContainer.RemoveChild(component.BottomRightButtons);
_gameHud.TopInventoryQuickButtonContainer.RemoveChild(component.TopQuickButtons);
component.AttachedToGameHud = false;
}
private void OnShutdown(EntityUid uid, ClientInventoryComponent component, ComponentShutdown args)
{
OnPlayerDetached(uid, component);
}
private void OnPlayerAttached(EntityUid uid, ClientInventoryComponent component, PlayerAttachedEvent args)
{
if(component.AttachedToGameHud) return;
_gameHud.InventoryButtonVisible = true;
_gameHud.BottomLeftInventoryQuickButtonContainer.AddChild(component.BottomLeftButtons);
_gameHud.BottomRightInventoryQuickButtonContainer.AddChild(component.BottomRightButtons);
_gameHud.TopInventoryQuickButtonContainer.AddChild(component.TopQuickButtons);
component.AttachedToGameHud = true;
}
private void UpdateHudTheme(int obj)
{
if (!_gameHud.ValidateHudTheme(obj))
{
return;
}
foreach (var inventoryComponent in EntityManager.EntityQuery<ClientInventoryComponent>(true))
{
foreach (var slotButton in inventoryComponent.SlotButtons)
{
foreach (var btn in slotButton.Value)
{
btn.RefreshTextures(_gameHud);
}
} }
} }
} }
@@ -55,9 +154,183 @@ namespace Content.Client.Inventory
public override void Shutdown() public override void Shutdown()
{ {
CommandBinds.Unregister<ClientInventorySystem>(); CommandBinds.Unregister<ClientInventorySystem>();
_config.UnsubValueChanged(CCVars.HudTheme, UpdateHudTheme);
base.Shutdown(); base.Shutdown();
} }
private void OnInit(EntityUid uid, ClientInventoryComponent component, ComponentInit args)
{
_clothingSystem.InitClothing(uid, component);
if (!TryGetUIElements(uid, out var window, out var bottomLeft, out var bottomRight, out var topQuick,
component))
return;
component.InventoryWindow = window;
component.BottomLeftButtons = bottomLeft;
component.BottomRightButtons = bottomRight;
component.TopQuickButtons = topQuick;
}
private void HoverInSlotButton(EntityUid uid, string slot, ItemSlotButton button, InventoryComponent? inventoryComponent = null, SharedHandsComponent? hands = null)
{
if (!Resolve(uid, ref inventoryComponent))
return;
if (!Resolve(uid, ref hands, false))
return;
if (!hands.TryGetActiveHeldEntity(out var heldEntity))
return;
if(!TryGetSlotContainer(uid, slot, out var containerSlot, out var slotDef, inventoryComponent))
return;
_itemSlotManager.HoverInSlot(button, heldEntity,
CanEquip(uid, heldEntity, slot, out _, slotDef, inventoryComponent) &&
containerSlot.CanInsert(heldEntity, EntityManager));
}
private void HandleSlotButtonPressed(EntityUid uid, string slot, ItemSlotButton button,
GUIBoundKeyEventArgs args)
{
if (TryGetSlotEntity(uid, slot, out var itemUid))
{
if (!_itemSlotManager.OnButtonPressed(args, itemUid.Value) && args.Function == EngineKeyFunctions.UIClick)
{
RaiseNetworkEvent(new UseSlotNetworkMessage(uid, slot));
}
return;
}
if (args.Function != EngineKeyFunctions.UIClick) return;
TryEquipActiveHandTo(uid, slot);
}
private bool TryGetUIElements(EntityUid uid, [NotNullWhen(true)] out SS14Window? invWindow,
[NotNullWhen(true)] out Control? invBottomLeft, [NotNullWhen(true)] out Control? invBottomRight,
[NotNullWhen(true)] out Control? invTopQuick, ClientInventoryComponent? component = null)
{
invWindow = null;
invBottomLeft = null;
invBottomRight = null;
invTopQuick = null;
if (!Resolve(uid, ref component))
return false;
if(!_prototypeManager.TryIndex<InventoryTemplatePrototype>(component.TemplateId, out var template))
return false;
if (!_uiGenerateDelegates.TryGetValue(component.TemplateId, out var genfunc))
{
_uiGenerateDelegates[component.TemplateId] = genfunc = (entityUid, list) =>
{
var window = new SS14Window()
{
Title = Loc.GetString("human-inventory-window-title"),
Resizable = false
};
window.OnClose += () => _gameHud.InventoryButtonDown = false;
var windowContents = new LayoutContainer
{
MinSize = (ButtonSize * 4 + ButtonSeparation * 3 + RightSeparation,
ButtonSize * 4 + ButtonSeparation * 3)
};
window.Contents.AddChild(windowContents);
ItemSlotButton GetButton(SlotDefinition definition, string textureBack)
{
var btn = new ItemSlotButton(ButtonSize, $"{definition.TextureName}.png", textureBack,
_gameHud)
{
OnStoragePressed = (e) =>
{
if (e.Function != EngineKeyFunctions.UIClick &&
e.Function != ContentKeyFunctions.ActivateItemInWorld)
return;
RaiseNetworkEvent(new OpenSlotStorageNetworkMessage(entityUid, definition.Name));
}
};
btn.OnHover = (_) =>
{
HoverInSlotButton(entityUid, definition.Name, btn);
};
btn.OnPressed = (e) =>
{
HandleSlotButtonPressed(entityUid, definition.Name, btn, e);
};
return btn;
}
void AddButton(SlotDefinition definition, Vector2i position)
{
var button = GetButton(definition, "back.png");
LayoutContainer.SetPosition(button, position);
windowContents.AddChild(button);
if (!list.ContainsKey(definition.Name))
list[definition.Name] = new();
list[definition.Name].Add(button);
}
void AddHUDButton(BoxContainer container, SlotDefinition definition)
{
var button = GetButton(definition, "back.png");
container.AddChild(button);
if (!list.ContainsKey(definition.Name))
list[definition.Name] = new();
list[definition.Name].Add(button);
}
var topQuick = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
SeparationOverride = 5
};
var bottomRight = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
SeparationOverride = 5
};
var bottomLeft = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
SeparationOverride = 5
};
const int sizep = (ButtonSize + ButtonSeparation);
foreach (var slotDefinition in template.Slots)
{
switch (slotDefinition.UIContainer)
{
case SlotUIContainer.BottomLeft:
AddHUDButton(bottomLeft, slotDefinition);
break;
case SlotUIContainer.BottomRight:
AddHUDButton(bottomRight, slotDefinition);
break;
case SlotUIContainer.Top:
AddHUDButton(topQuick, slotDefinition);
break;
}
AddButton(slotDefinition, slotDefinition.UIWindowPosition * sizep);
}
return (window, bottomLeft, bottomRight, topQuick);
};
}
var res = genfunc(uid, component.SlotButtons);
invWindow = res.window;
invBottomLeft = res.bottomLeft;
invBottomRight = res.bottomRight;
invTopQuick = res.topQuick;
return true;
}
private void HandleOpenInventoryMenu() private void HandleOpenInventoryMenu()
{ {
_gameHud.InventoryButtonDown = !_gameHud.InventoryButtonDown; _gameHud.InventoryButtonDown = !_gameHud.InventoryButtonDown;

View File

@@ -1,334 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Content.Client.HUD;
using Content.Client.Items.Managers;
using Content.Client.Items.UI;
using Content.Shared.CCVar;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using static Content.Shared.Inventory.EquipmentSlotDefines;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Inventory
{
// Dynamically instantiated by ClientInventoryComponent.
[UsedImplicitly]
public class HumanInventoryInterfaceController : InventoryInterfaceController
{
[Dependency] private readonly IGameHud _gameHud = default!;
[Dependency] private readonly IItemSlotManager _itemSlotManager = default!;
[Dependency] private readonly INetConfigurationManager _configManager = default!;
private readonly Dictionary<Slots, List<ItemSlotButton>> _inventoryButtons
= new();
private ItemSlotButton _hudButtonPocket1 = default!;
private ItemSlotButton _hudButtonPocket2 = default!;
private ItemSlotButton _hudButtonShoes = default!;
private ItemSlotButton _hudButtonJumpsuit = default!;
private ItemSlotButton _hudButtonGloves = default!;
private ItemSlotButton _hudButtonNeck = default!;
private ItemSlotButton _hudButtonHead = default!;
private ItemSlotButton _hudButtonBelt = default!;
private ItemSlotButton _hudButtonBack = default!;
private ItemSlotButton _hudButtonOClothing = default!;
private ItemSlotButton _hudButtonId = default!;
private ItemSlotButton _hudButtonMask = default!;
private ItemSlotButton _hudButtonEyes = default!;
private ItemSlotButton _hudButtonEars = default!;
private Control _topQuickButtonsContainer = default!;
private Control _bottomLeftQuickButtonsContainer = default!;
private Control _bottomRightQuickButtonsContainer = default!;
public HumanInventoryInterfaceController(ClientInventoryComponent owner) : base(owner)
{
}
public override void Initialize()
{
base.Initialize();
_configManager.OnValueChanged(CCVars.HudTheme, UpdateHudTheme, invokeImmediately: true);
_window = new HumanInventoryWindow(_gameHud);
_window.OnClose += () => GameHud.InventoryButtonDown = false;
foreach (var (slot, button) in _window.Buttons)
{
button.OnPressed = (e) => AddToInventory(e, slot);
button.OnStoragePressed = (e) => OpenStorage(e, slot);
button.OnHover = (_) => RequestItemHover(slot);
_inventoryButtons.Add(slot, new List<ItemSlotButton> {button});
}
void AddButton(out ItemSlotButton variable, Slots slot, string textureName)
{
var texture = _gameHud.GetHudTexture($"{textureName}.png");
var storageTexture = _gameHud.GetHudTexture("back.png");
variable = new ItemSlotButton(texture, storageTexture, textureName)
{
OnPressed = (e) => AddToInventory(e, slot),
OnStoragePressed = (e) => OpenStorage(e, slot),
OnHover = (_) => RequestItemHover(slot)
};
_inventoryButtons[slot].Add(variable);
}
AddButton(out _hudButtonPocket1, Slots.POCKET1, "pocket");
AddButton(out _hudButtonPocket2, Slots.POCKET2, "pocket");
AddButton(out _hudButtonId, Slots.IDCARD, "id");
AddButton(out _hudButtonBack, Slots.BACKPACK, "back");
AddButton(out _hudButtonBelt, Slots.BELT, "belt");
AddButton(out _hudButtonShoes, Slots.SHOES, "shoes");
AddButton(out _hudButtonJumpsuit, Slots.INNERCLOTHING, "uniform");
AddButton(out _hudButtonOClothing, Slots.OUTERCLOTHING, "suit");
AddButton(out _hudButtonGloves, Slots.GLOVES, "gloves");
AddButton(out _hudButtonNeck, Slots.NECK, "neck");
AddButton(out _hudButtonMask, Slots.MASK, "mask");
AddButton(out _hudButtonEyes, Slots.EYES, "glasses");
AddButton(out _hudButtonEars, Slots.EARS, "ears");
AddButton(out _hudButtonHead, Slots.HEAD, "head");
_topQuickButtonsContainer = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Children =
{
_hudButtonShoes,
_hudButtonJumpsuit,
_hudButtonOClothing,
_hudButtonGloves,
_hudButtonNeck,
_hudButtonMask,
_hudButtonEyes,
_hudButtonEars,
_hudButtonHead
},
SeparationOverride = 5
};
_bottomRightQuickButtonsContainer = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Children =
{
_hudButtonPocket1,
_hudButtonPocket2,
_hudButtonId,
},
SeparationOverride = 5
};
_bottomLeftQuickButtonsContainer = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Children =
{
_hudButtonBelt,
_hudButtonBack
},
SeparationOverride = 5
};
}
public override SS14Window? Window => _window;
private HumanInventoryWindow? _window;
public override IEnumerable<ItemSlotButton> GetItemSlotButtons(Slots slot)
{
if (!_inventoryButtons.TryGetValue(slot, out var buttons))
{
return Enumerable.Empty<ItemSlotButton>();
}
return buttons;
}
public override void AddToSlot(Slots slot, EntityUid entity)
{
base.AddToSlot(slot, entity);
if (!_inventoryButtons.TryGetValue(slot, out var buttons))
return;
foreach (var button in buttons)
{
_itemSlotManager.SetItemSlot(button, entity);
button.OnPressed = (e) => HandleInventoryKeybind(e, slot);
}
}
public override void RemoveFromSlot(Slots slot)
{
base.RemoveFromSlot(slot);
if (!_inventoryButtons.TryGetValue(slot, out var buttons))
{
return;
}
foreach (var button in buttons)
{
ClearButton(button, slot);
}
}
public override void HoverInSlot(Slots slot, EntityUid entity, bool fits)
{
base.HoverInSlot(slot, entity, fits);
if (!_inventoryButtons.TryGetValue(slot, out var buttons))
{
return;
}
foreach (var button in buttons)
{
_itemSlotManager.HoverInSlot(button, entity, fits);
}
}
protected override void HandleInventoryKeybind(GUIBoundKeyEventArgs args, Slots slot)
{
if (!_inventoryButtons.ContainsKey(slot))
return;
if (!Owner.TryGetSlot(slot, out var item))
return;
if (!_itemSlotManager.OnButtonPressed(args, item.Value))
base.HandleInventoryKeybind(args, slot);
}
private void ClearButton(ItemSlotButton button, Slots slot)
{
button.OnPressed = (e) => AddToInventory(e, slot);
_itemSlotManager.SetItemSlot(button, default);
}
public override void PlayerAttached()
{
base.PlayerAttached();
GameHud.BottomLeftInventoryQuickButtonContainer.AddChild(_bottomLeftQuickButtonsContainer);
GameHud.BottomRightInventoryQuickButtonContainer.AddChild(_bottomRightQuickButtonsContainer);
GameHud.TopInventoryQuickButtonContainer.AddChild(_topQuickButtonsContainer);
// Update all the buttons to make sure they check out.
foreach (var (slot, buttons) in _inventoryButtons)
{
foreach (var button in buttons)
{
ClearButton(button, slot);
}
if (Owner.TryGetSlot(slot, out var entity))
{
AddToSlot(slot, entity.Value);
}
}
}
public override void PlayerDetached()
{
base.PlayerDetached();
GameHud.BottomRightInventoryQuickButtonContainer.RemoveChild(_bottomRightQuickButtonsContainer);
GameHud.BottomLeftInventoryQuickButtonContainer.RemoveChild(_bottomLeftQuickButtonsContainer);
GameHud.TopInventoryQuickButtonContainer.RemoveChild(_topQuickButtonsContainer);
foreach (var (slot, list) in _inventoryButtons)
{
foreach (var button in list)
{
ClearButton(button, slot);
}
}
}
public void UpdateHudTheme(int idx)
{
if (!_gameHud.ValidateHudTheme(idx))
{
return;
}
foreach (var (_, list) in _inventoryButtons)
{
foreach (var button in list)
{
button.Button.Texture = _gameHud.GetHudTexture($"{button.TextureName}.png");
button.StorageButton.TextureNormal = _gameHud.GetHudTexture("back.png");
}
}
}
private class HumanInventoryWindow : SS14Window
{
private const int ButtonSize = 64;
private const int ButtonSeparation = 4;
private const int RightSeparation = 2;
public IReadOnlyDictionary<Slots, ItemSlotButton> Buttons { get; }
public HumanInventoryWindow(IGameHud gameHud)
{
Title = Loc.GetString("human-inventory-window-title");
Resizable = false;
var buttonDict = new Dictionary<Slots, ItemSlotButton>();
Buttons = buttonDict;
const int width = ButtonSize * 4 + ButtonSeparation * 3 + RightSeparation;
const int height = ButtonSize * 4 + ButtonSeparation * 3;
var windowContents = new LayoutContainer {MinSize = (width, height)};
Contents.AddChild(windowContents);
void AddButton(Slots slot, string textureName, Vector2 position)
{
var texture = gameHud.GetHudTexture($"{textureName}.png");
var storageTexture = gameHud.GetHudTexture("back.png");
var button = new ItemSlotButton(texture, storageTexture, textureName);
LayoutContainer.SetPosition(button, position);
windowContents.AddChild(button);
buttonDict.Add(slot, button);
}
const int sizep = (ButtonSize + ButtonSeparation);
// Left column.
AddButton(Slots.EYES, "glasses", (0, 0));
AddButton(Slots.NECK, "neck", (0, sizep));
AddButton(Slots.INNERCLOTHING, "uniform", (0, 2 * sizep));
AddButton(Slots.POCKET1, "pocket", (0, 3 * sizep));
// Middle column.
AddButton(Slots.HEAD, "head", (sizep, 0));
AddButton(Slots.MASK, "mask", (sizep, sizep));
AddButton(Slots.OUTERCLOTHING, "suit", (sizep, 2 * sizep));
AddButton(Slots.SHOES, "shoes", (sizep, 3 * sizep));
// Right column
AddButton(Slots.EARS, "ears", (2 * sizep, 0));
AddButton(Slots.IDCARD, "id", (2 * sizep, sizep));
AddButton(Slots.GLOVES, "gloves", (2 * sizep, 2 * sizep));
AddButton(Slots.POCKET2, "pocket", (2 * sizep, 3 * sizep));
// Far right column.
AddButton(Slots.BACKPACK, "back", (3 * sizep, 0));
AddButton(Slots.BELT, "belt", (3 * sizep, sizep));
}
}
}
}

View File

@@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using Content.Client.HUD;
using Content.Client.Items.UI;
using Content.Shared.Input;
using Content.Shared.Inventory;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.IoC;
namespace Content.Client.Inventory
{
public abstract class InventoryInterfaceController : IDisposable
{
[Dependency] protected readonly IGameHud GameHud = default!;
protected InventoryInterfaceController(ClientInventoryComponent owner)
{
Owner = owner;
}
public virtual void Initialize()
{
}
public abstract SS14Window? Window { get; }
protected ClientInventoryComponent Owner { get; }
public virtual void PlayerAttached()
{
GameHud.InventoryButtonVisible = true;
}
public virtual void PlayerDetached()
{
GameHud.InventoryButtonVisible = false;
}
public virtual void Dispose()
{
}
/// <returns>the button controls associated with the
/// specified slot, if any. Empty if none.</returns>
public abstract IEnumerable<ItemSlotButton> GetItemSlotButtons(EquipmentSlotDefines.Slots slot);
public virtual void AddToSlot(EquipmentSlotDefines.Slots slot, EntityUid entity)
{
}
public virtual void HoverInSlot(EquipmentSlotDefines.Slots slot, EntityUid entity, bool fits)
{
}
public virtual void RemoveFromSlot(EquipmentSlotDefines.Slots slot)
{
}
protected virtual void HandleInventoryKeybind(GUIBoundKeyEventArgs args, EquipmentSlotDefines.Slots slot)
{
if (args.Function == EngineKeyFunctions.UIClick)
{
UseItemOnInventory(slot);
}
}
protected void AddToInventory(GUIBoundKeyEventArgs args, EquipmentSlotDefines.Slots slot)
{
if (args.Function != EngineKeyFunctions.UIClick)
{
return;
}
Owner.SendEquipMessage(slot);
}
protected void UseItemOnInventory(EquipmentSlotDefines.Slots slot)
{
Owner.SendUseMessage(slot);
}
protected void OpenStorage(GUIBoundKeyEventArgs args, EquipmentSlotDefines.Slots slot)
{
if (args.Function != EngineKeyFunctions.UIClick && args.Function != ContentKeyFunctions.ActivateItemInWorld)
{
return;
}
Owner.SendOpenStorageUIMessage(slot);
}
protected void RequestItemHover(EquipmentSlotDefines.Slots slot)
{
Owner.SendHoverMessage(slot);
}
}
}

View File

@@ -7,14 +7,13 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Client.Inventory namespace Content.Client.Inventory
{ {
[UsedImplicitly] [UsedImplicitly]
public class StrippableBoundUserInterface : BoundUserInterface public class StrippableBoundUserInterface : BoundUserInterface
{ {
public Dictionary<Slots, string>? Inventory { get; private set; } public Dictionary<(string ID, string Name), string>? Inventory { get; private set; }
public Dictionary<string, string>? Hands { get; private set; } public Dictionary<string, string>? Hands { get; private set; }
public Dictionary<EntityUid, string>? Handcuffs { get; private set; } public Dictionary<EntityUid, string>? Handcuffs { get; private set; }
@@ -55,9 +54,9 @@ namespace Content.Client.Inventory
{ {
foreach (var (slot, name) in Inventory) foreach (var (slot, name) in Inventory)
{ {
_strippingMenu.AddButton(SlotNames[slot], name, (ev) => _strippingMenu.AddButton(slot.Name, name, (ev) =>
{ {
SendMessage(new StrippingInventoryButtonPressed(slot)); SendMessage(new StrippingInventoryButtonPressed(slot.ID));
}); });
} }
} }

View File

@@ -9,10 +9,10 @@ namespace Content.Client.Items.Managers
{ {
bool OnButtonPressed(GUIBoundKeyEventArgs args, EntityUid item); bool OnButtonPressed(GUIBoundKeyEventArgs args, EntityUid item);
void UpdateCooldown(ItemSlotButton? cooldownTexture, EntityUid entity); void UpdateCooldown(ItemSlotButton? cooldownTexture, EntityUid entity);
bool SetItemSlot(ItemSlotButton button, EntityUid entity); bool SetItemSlot(ItemSlotButton button, EntityUid? entity);
void HoverInSlot(ItemSlotButton button, EntityUid entity, bool fits); void HoverInSlot(ItemSlotButton button, EntityUid entity, bool fits);
event Action<EntitySlotHighlightedEventArgs>? EntityHighlightedUpdated; event Action<EntitySlotHighlightedEventArgs>? EntityHighlightedUpdated;
bool IsHighlighted(EntityUid uid); bool IsHighlighted(EntityUid? uid);
/// <summary> /// <summary>
/// Highlight all slot controls that contain the specified entity. /// Highlight all slot controls that contain the specified entity.

View File

@@ -28,9 +28,9 @@ namespace Content.Client.Items.Managers
public event Action<EntitySlotHighlightedEventArgs>? EntityHighlightedUpdated; public event Action<EntitySlotHighlightedEventArgs>? EntityHighlightedUpdated;
public bool SetItemSlot(ItemSlotButton button, EntityUid entity) public bool SetItemSlot(ItemSlotButton button, EntityUid? entity)
{ {
if (entity == default) if (entity == null)
{ {
button.SpriteView.Sprite = null; button.SpriteView.Sprite = null;
button.StorageButton.Visible = false; button.StorageButton.Visible = false;
@@ -141,9 +141,10 @@ namespace Content.Client.Items.Managers
button.HoverSpriteView.Sprite = hoverSprite; button.HoverSpriteView.Sprite = hoverSprite;
} }
public bool IsHighlighted(EntityUid uid) public bool IsHighlighted(EntityUid? uid)
{ {
return _highlightEntities.Contains(uid); if (uid == null) return false;
return _highlightEntities.Contains(uid.Value);
} }
public void HighlightEntity(EntityUid uid) public void HighlightEntity(EntityUid uid)

View File

@@ -1,15 +1,18 @@
using System; using System;
using Content.Client.Cooldown; using Content.Client.Cooldown;
using Content.Client.HUD;
using Content.Client.Items.Managers; using Content.Client.Items.Managers;
using Content.Client.Stylesheets; using Content.Client.Stylesheets;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.Utility;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Input; using Robust.Shared.Input;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Utility;
namespace Content.Client.Items.UI namespace Content.Client.Items.UI
{ {
@@ -19,7 +22,7 @@ namespace Content.Client.Items.UI
[Dependency] private readonly IItemSlotManager _itemSlotManager = default!; [Dependency] private readonly IItemSlotManager _itemSlotManager = default!;
public EntityUid Entity { get; set; } public EntityUid? Entity { get; set; }
public TextureRect Button { get; } public TextureRect Button { get; }
public SpriteView SpriteView { get; } public SpriteView SpriteView { get; }
public SpriteView HoverSpriteView { get; } public SpriteView HoverSpriteView { get; }
@@ -35,19 +38,19 @@ namespace Content.Client.Items.UI
private readonly PanelContainer _highlightRect; private readonly PanelContainer _highlightRect;
public string TextureName { get; set; } private string _textureName;
private string _storageTextureName;
public ItemSlotButton(Texture texture, Texture storageTexture, string textureName) public ItemSlotButton(int size, string textureName, string storageTextureName, IGameHud gameHud)
{ {
_textureName = textureName;
_storageTextureName = storageTextureName;
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
MinSize = (64, 64); MinSize = (size, size);
TextureName = textureName;
AddChild(Button = new TextureRect AddChild(Button = new TextureRect
{ {
Texture = texture,
TextureScale = (2, 2), TextureScale = (2, 2),
MouseFilter = MouseFilterMode.Stop MouseFilter = MouseFilterMode.Stop
}); });
@@ -75,7 +78,6 @@ namespace Content.Client.Items.UI
AddChild(StorageButton = new TextureButton AddChild(StorageButton = new TextureButton
{ {
TextureNormal = storageTexture,
Scale = (0.75f, 0.75f), Scale = (0.75f, 0.75f),
HorizontalAlignment = HAlignment.Right, HorizontalAlignment = HAlignment.Right,
VerticalAlignment = VAlignment.Bottom, VerticalAlignment = VAlignment.Bottom,
@@ -108,6 +110,14 @@ namespace Content.Client.Items.UI
{ {
Visible = false, Visible = false,
}); });
RefreshTextures(gameHud);
}
public void RefreshTextures(IGameHud gameHud)
{
Button.Texture = gameHud.GetHudTexture(_textureName);
StorageButton.TextureNormal = gameHud.GetHudTexture(_storageTextureName);
} }
protected override void EnteredTree() protected override void EnteredTree()

View File

@@ -4,6 +4,7 @@ using Content.Client.Inventory;
using Content.Client.Preferences; using Content.Client.Preferences;
using Content.Shared.CharacterAppearance.Systems; using Content.Shared.CharacterAppearance.Systems;
using Content.Shared.GameTicking; using Content.Shared.GameTicking;
using Content.Shared.Inventory;
using Content.Shared.Preferences; using Content.Shared.Preferences;
using Content.Shared.Roles; using Content.Shared.Roles;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
@@ -15,7 +16,6 @@ using Robust.Shared.Localization;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using static Content.Shared.Inventory.EquipmentSlotDefines;
using static Robust.Client.UserInterface.Controls.BoxContainer; using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Lobby.UI namespace Content.Client.Lobby.UI
@@ -141,29 +141,30 @@ namespace Content.Client.Lobby.UI
public static void GiveDummyJobClothes(EntityUid dummy, HumanoidCharacterProfile profile) public static void GiveDummyJobClothes(EntityUid dummy, HumanoidCharacterProfile profile)
{ {
var protoMan = IoCManager.Resolve<IPrototypeManager>(); var protoMan = IoCManager.Resolve<IPrototypeManager>();
var entMan = IoCManager.Resolve<IEntityManager>(); var entMan = IoCManager.Resolve<IEntityManager>();
var inventory = entMan.GetComponent<ClientInventoryComponent>(dummy); var invSystem = EntitySystem.Get<ClientInventorySystem>();
var highPriorityJob = profile.JobPriorities.FirstOrDefault(p => p.Value == JobPriority.High).Key; var highPriorityJob = profile.JobPriorities.FirstOrDefault(p => p.Value == JobPriority.High).Key;
// ReSharper disable once ConstantNullCoalescingCondition // ReSharper disable once ConstantNullCoalescingCondition
var job = protoMan.Index<JobPrototype>(highPriorityJob ?? SharedGameTicker.FallbackOverflowJob); var job = protoMan.Index<JobPrototype>(highPriorityJob ?? SharedGameTicker.FallbackOverflowJob);
inventory.ClearAllSlotVisuals(); if (job.StartingGear != null && invSystem.TryGetSlots(dummy, out var slots))
if (job.StartingGear != null)
{ {
var gear = protoMan.Index<StartingGearPrototype>(job.StartingGear); var gear = protoMan.Index<StartingGearPrototype>(job.StartingGear);
foreach (var slot in AllSlots) foreach (var slot in slots)
{ {
var itemType = gear.GetGear(slot, profile); var itemType = gear.GetGear(slot.Name, profile);
if(invSystem.TryUnequip(dummy, slot.Name, out var unequippedItem, true, true))
{
entMan.DeleteEntity(unequippedItem.Value);
}
if (itemType != string.Empty) if (itemType != string.Empty)
{ {
var item = entMan.SpawnEntity(itemType, MapCoordinates.Nullspace); var item = entMan.SpawnEntity(itemType, MapCoordinates.Nullspace);
inventory.SetSlotVisuals(slot, item); invSystem.TryEquip(dummy, item, slot.Name, true, true);
entMan.DeleteEntity(item);
} }
} }
} }

View File

@@ -46,17 +46,17 @@ namespace Content.Client.Smoking
{ {
case SmokableState.Lit: case SmokableState.Lit:
if (clothing != null) if (clothing != null)
clothing.ClothingEquippedPrefix = _litPrefix; clothing.EquippedPrefix = _litPrefix;
sprite.LayerSetState(0, _litIcon); sprite.LayerSetState(0, _litIcon);
break; break;
case SmokableState.Burnt: case SmokableState.Burnt:
if (clothing != null) if (clothing != null)
clothing.ClothingEquippedPrefix = _burntPrefix; clothing.EquippedPrefix = _burntPrefix;
sprite.LayerSetState(0, _burntIcon); sprite.LayerSetState(0, _burntIcon);
break; break;
case SmokableState.Unlit: case SmokableState.Unlit:
if (clothing != null) if (clothing != null)
clothing.ClothingEquippedPrefix = _unlitPrefix; clothing.EquippedPrefix = _unlitPrefix;
sprite.LayerSetState(0, _unlitIcon); sprite.LayerSetState(0, _unlitIcon);
break; break;
} }

View File

@@ -1,11 +1,11 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Buckle.Components; using Content.Server.Buckle.Components;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
using Content.Shared.Body.Components; using Content.Shared.Body.Components;
using Content.Shared.Body.Part; using Content.Shared.Body.Part;
using Content.Shared.Buckle.Components; using Content.Shared.Buckle.Components;
using Content.Shared.Item;
using Content.Shared.Standing; using Content.Shared.Standing;
using NUnit.Framework; using NUnit.Framework;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -252,7 +252,7 @@ namespace Content.IntegrationTests.Tests.Buckle
var akms = entityManager.SpawnEntity(ItemDummyId, coordinates); var akms = entityManager.SpawnEntity(ItemDummyId, coordinates);
// Equip items // Equip items
Assert.True(entityManager.TryGetComponent(akms, out ItemComponent item)); Assert.True(entityManager.TryGetComponent(akms, out SharedItemComponent item));
Assert.True(hands.PutInHand(item)); Assert.True(hands.PutInHand(item));
} }
}); });

View File

@@ -1,11 +1,13 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Clothing.Components; using Content.Server.Clothing.Components;
using Content.Server.Inventory.Components; using Content.Server.Inventory;
using Content.Shared.Inventory;
using Content.Shared.Item;
using NUnit.Framework; using NUnit.Framework;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.IntegrationTests.Tests namespace Content.IntegrationTests.Tests
{ {
@@ -19,23 +21,25 @@ namespace Content.IntegrationTests.Tests
{ {
var server = StartServer(); var server = StartServer();
server.Assert(() => await server.WaitAssertion(() =>
{ {
// Spawn everything. // Spawn everything.
var mapMan = IoCManager.Resolve<IMapManager>(); var mapMan = IoCManager.Resolve<IMapManager>();
var invSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<InventorySystem>();
mapMan.CreateNewMapEntity(MapId.Nullspace); mapMan.CreateNewMapEntity(MapId.Nullspace);
var entMgr = IoCManager.Resolve<IEntityManager>(); var entMgr = IoCManager.Resolve<IEntityManager>();
var container = entMgr.SpawnEntity(null, MapCoordinates.Nullspace); var container = entMgr.SpawnEntity(null, MapCoordinates.Nullspace);
var inv = entMgr.AddComponent<InventoryComponent>(container); entMgr.AddComponent<ServerInventoryComponent>(container);
entMgr.AddComponent<ContainerManagerComponent>(container);
var child = entMgr.SpawnEntity(null, MapCoordinates.Nullspace); var child = entMgr.SpawnEntity(null, MapCoordinates.Nullspace);
var item = entMgr.AddComponent<ClothingComponent>(child); var item = entMgr.AddComponent<ItemComponent>(child);
item.SlotFlags = SlotFlags.HEAD; item.SlotFlags = SlotFlags.HEAD;
// Equip item. // Equip item.
Assert.That(inv.Equip(Slots.HEAD, item, false), Is.True); Assert.That(invSystem.TryEquip(container, child, "head"), Is.True);
// Delete parent. // Delete parent.
entMgr.DeleteEntity(container); entMgr.DeleteEntity(container);
@@ -43,8 +47,6 @@ namespace Content.IntegrationTests.Tests
// Assert that child item was also deleted. // Assert that child item was also deleted.
Assert.That(item.Deleted, Is.True); Assert.That(item.Deleted, Is.True);
}); });
await server.WaitIdleAsync();
} }
} }
} }

View File

@@ -3,19 +3,19 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Client.Actions; using Content.Client.Actions;
using Content.Client.Actions.UI; using Content.Client.Actions.UI;
using Content.Client.Items.Components;
using Content.Server.Actions; using Content.Server.Actions;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Actions.Components; using Content.Shared.Actions.Components;
using Content.Shared.Actions.Prototypes; using Content.Shared.Actions.Prototypes;
using Content.Shared.Cooldown; using Content.Shared.Cooldown;
using Content.Shared.Item;
using NUnit.Framework; using NUnit.Framework;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared; using Robust.Shared;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -268,7 +268,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs
// grant an extra item action, before pickup, initially disabled // grant an extra item action, before pickup, initially disabled
itemActions.GrantOrUpdate(ItemActionType.DebugToggle, false); itemActions.GrantOrUpdate(ItemActionType.DebugToggle, false);
serverEntManager.GetComponent<HandsComponent>(serverPlayerEnt).PutInHand(serverEntManager.GetComponent<ItemComponent>(serverFlashlight), false); serverEntManager.GetComponent<HandsComponent>(serverPlayerEnt).PutInHand(serverEntManager.GetComponent<SharedItemComponent>(serverFlashlight), false);
// grant an extra item action, after pickup, with a cooldown // grant an extra item action, after pickup, with a cooldown
itemActions.GrantOrUpdate(ItemActionType.DebugInstant, cooldown: cooldown); itemActions.GrantOrUpdate(ItemActionType.DebugInstant, cooldown: cooldown);
@@ -360,7 +360,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs
{ {
// pick the item up again, the states should be back to what they were when dropped, // pick the item up again, the states should be back to what they were when dropped,
// as the states "stick" with the item // as the states "stick" with the item
serverEntManager.GetComponent<HandsComponent>(serverPlayerEnt).PutInHand(serverEntManager.GetComponent<ItemComponent>(serverFlashlight), false); serverEntManager.GetComponent<HandsComponent>(serverPlayerEnt).PutInHand(serverEntManager.GetComponent<SharedItemComponent>(serverFlashlight), false);
Assert.That(serverActionsComponent.ItemActionStates().TryGetValue(serverFlashlight, out var lightStates)); Assert.That(serverActionsComponent.ItemActionStates().TryGetValue(serverFlashlight, out var lightStates));
Assert.That(lightStates.TryGetValue(ItemActionType.ToggleLight, out var lightState)); Assert.That(lightStates.TryGetValue(ItemActionType.ToggleLight, out var lightState));
Assert.That(lightState.Equals(new ActionState(true, toggledOn: true))); Assert.That(lightState.Equals(new ActionState(true, toggledOn: true)));

View File

@@ -1,18 +1,17 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Inventory.Components; using Content.Server.Inventory;
using Content.Shared.Inventory;
using NUnit.Framework; using NUnit.Framework;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.IntegrationTests.Tests namespace Content.IntegrationTests.Tests
{ {
// Tests the behavior of HumanInventoryControllerComponent. // Tests the behavior of InventoryComponent.
// i.e. the interaction between uniforms and the pocket/ID slots. // i.e. the interaction between uniforms and the pocket/ID slots.
// and also how big items don't fit in pockets. // and also how big items don't fit in pockets.
[TestFixture] [TestFixture]
[TestOf(typeof(HumanInventoryControllerComponent))]
public class HumanInventoryUniformSlotsTest : ContentIntegrationTest public class HumanInventoryUniformSlotsTest : ContentIntegrationTest
{ {
private const string Prototypes = @" private const string Prototypes = @"
@@ -21,7 +20,7 @@ namespace Content.IntegrationTests.Tests
id: HumanDummy id: HumanDummy
components: components:
- type: Inventory - type: Inventory
- type: HumanInventoryController - type: ContainerContainer
- type: entity - type: entity
name: UniformDummy name: UniformDummy
@@ -67,8 +66,11 @@ namespace Content.IntegrationTests.Tests
EntityUid pocketItem = default; EntityUid pocketItem = default;
InventoryComponent inventory = null; InventoryComponent inventory = null;
InventorySystem invSystem = default!;
server.Assert(() => server.Assert(() =>
{ {
invSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<InventorySystem>();
var mapMan = IoCManager.Resolve<IMapManager>(); var mapMan = IoCManager.Resolve<IMapManager>();
mapMan.CreateNewMapEntity(MapId.Nullspace); mapMan.CreateNewMapEntity(MapId.Nullspace);
@@ -81,26 +83,25 @@ namespace Content.IntegrationTests.Tests
pocketItem = entityMan.SpawnEntity("FlashlightDummy", MapCoordinates.Nullspace); pocketItem = entityMan.SpawnEntity("FlashlightDummy", MapCoordinates.Nullspace);
var tooBigItem = entityMan.SpawnEntity("ToolboxDummy", MapCoordinates.Nullspace); var tooBigItem = entityMan.SpawnEntity("ToolboxDummy", MapCoordinates.Nullspace);
inventory = entityMan.GetComponent<InventoryComponent>(human);
Assert.That(inventory.CanEquip(Slots.INNERCLOTHING, uniform)); Assert.That(invSystem.CanEquip(human, uniform, "jumpsuit", out _));
// Can't equip any of these since no uniform! // Can't equip any of these since no uniform!
Assert.That(inventory.CanEquip(Slots.IDCARD, idCard), Is.False); Assert.That(invSystem.CanEquip(human, idCard, "id", out _), Is.False);
Assert.That(inventory.CanEquip(Slots.POCKET1, pocketItem), Is.False); Assert.That(invSystem.CanEquip(human, pocketItem, "pocket1", out _), Is.False);
Assert.That(inventory.CanEquip(Slots.POCKET1, tooBigItem), Is.False); // This one fails either way. Assert.That(invSystem.CanEquip(human, tooBigItem, "pocket2", out _), Is.False); // This one fails either way.
inventory.Equip(Slots.INNERCLOTHING, uniform); Assert.That(invSystem.TryEquip(human, uniform, "jumpsuit"));
Assert.That(inventory.Equip(Slots.IDCARD, idCard)); Assert.That(invSystem.TryEquip(human, idCard, "id"));
Assert.That(inventory.Equip(Slots.POCKET1, pocketItem)); Assert.That(invSystem.CanEquip(human, tooBigItem, "pocket1", out _), Is.False); // Still failing!
Assert.That(inventory.CanEquip(Slots.POCKET1, tooBigItem), Is.False); // Still failing! Assert.That(invSystem.TryEquip(human, pocketItem, "pocket1"));
Assert.That(IsDescendant(idCard, human)); Assert.That(IsDescendant(idCard, human));
Assert.That(IsDescendant(pocketItem, human)); Assert.That(IsDescendant(pocketItem, human));
// Now drop the jumpsuit. // Now drop the jumpsuit.
inventory.Unequip(Slots.INNERCLOTHING); Assert.That(invSystem.TryUnequip(human, "jumpsuit"));
}); });
server.RunTicks(2); server.RunTicks(2);
@@ -113,9 +114,9 @@ namespace Content.IntegrationTests.Tests
Assert.That(IsDescendant(pocketItem, human), Is.False); Assert.That(IsDescendant(pocketItem, human), Is.False);
// Ensure everything null here. // Ensure everything null here.
Assert.That(inventory.GetSlotItem(Slots.INNERCLOTHING), Is.Null); Assert.That(!invSystem.TryGetSlotEntity(human, "jumpsuit", out _));
Assert.That(inventory.GetSlotItem(Slots.IDCARD), Is.Null); Assert.That(!invSystem.TryGetSlotEntity(human, "id", out _));
Assert.That(inventory.GetSlotItem(Slots.POCKET1), Is.Null); Assert.That(!invSystem.TryGetSlotEntity(human, "pocket1", out _));
}); });
await server.WaitIdleAsync(); await server.WaitIdleAsync();

View File

@@ -1,10 +1,11 @@
#nullable enable annotations #nullable enable annotations
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Client.Items.Components;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Interaction; using Content.Server.Interaction;
using Content.Server.Items;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Melee;
using NUnit.Framework; using NUnit.Framework;
using Robust.Shared.Containers; using Robust.Shared.Containers;
@@ -13,6 +14,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Reflection; using Robust.Shared.Reflection;
using ItemComponent = Content.Server.Clothing.Components.ItemComponent;
namespace Content.IntegrationTests.Tests.Interaction.Click namespace Content.IntegrationTests.Tests.Interaction.Click
{ {
@@ -97,7 +99,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
Assert.That(interactHand); Assert.That(interactHand);
Assert.That(sEntities.TryGetComponent<HandsComponent>(user, out var hands)); Assert.That(sEntities.TryGetComponent<HandsComponent>(user, out var hands));
Assert.That(hands.PutInHand(sEntities.GetComponent<ItemComponent>(item))); Assert.That(hands.PutInHand(sEntities.GetComponent<SharedItemComponent>(item)));
interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target); interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target);
Assert.That(interactUsing); Assert.That(interactUsing);
@@ -169,7 +171,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
Assert.That(interactHand, Is.False); Assert.That(interactHand, Is.False);
Assert.That(sEntities.TryGetComponent<HandsComponent?>(user, out var hands)); Assert.That(sEntities.TryGetComponent<HandsComponent?>(user, out var hands));
Assert.That(hands.PutInHand(sEntities.GetComponent<ItemComponent>(item))); Assert.That(hands.PutInHand(sEntities.GetComponent<SharedItemComponent>(item)));
interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target); interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target);
Assert.That(interactUsing, Is.False); Assert.That(interactUsing, Is.False);
@@ -238,7 +240,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
Assert.That(interactHand); Assert.That(interactHand);
Assert.That(sEntities.TryGetComponent<HandsComponent>(user, out var hands)); Assert.That(sEntities.TryGetComponent<HandsComponent>(user, out var hands));
Assert.That(hands.PutInHand(sEntities.GetComponent<ItemComponent>(item))); Assert.That(hands.PutInHand(sEntities.GetComponent<SharedItemComponent>(item)));
interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target); interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target);
Assert.That(interactUsing); Assert.That(interactUsing);
@@ -308,7 +310,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
Assert.That(interactHand, Is.False); Assert.That(interactHand, Is.False);
Assert.That(sEntities.TryGetComponent<HandsComponent?>(user, out var hands)); Assert.That(sEntities.TryGetComponent<HandsComponent?>(user, out var hands));
Assert.That(hands.PutInHand(sEntities.GetComponent<ItemComponent>(item))); Assert.That(hands.PutInHand(sEntities.GetComponent<SharedItemComponent>(item)));
interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target); interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target);
Assert.That(interactUsing, Is.False); Assert.That(interactUsing, Is.False);
@@ -393,7 +395,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click
Assert.That(interactHand); Assert.That(interactHand);
Assert.That(sEntities.TryGetComponent<HandsComponent?>(user, out var hands)); Assert.That(sEntities.TryGetComponent<HandsComponent?>(user, out var hands));
Assert.That(hands.PutInHand(sEntities.GetComponent<ItemComponent>(item))); Assert.That(hands.PutInHand(sEntities.GetComponent<SharedItemComponent>(item)));
interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target); interactionSystem.UserInteraction(user, sEntities.GetComponent<TransformComponent>(target).Coordinates, target);
Assert.That(interactUsing, Is.False); Assert.That(interactUsing, Is.False);

View File

@@ -1,19 +1,16 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Inventory; using Content.Server.Inventory;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.Stunnable; using Content.Server.Stunnable;
using Content.Shared.Inventory;
using NUnit.Framework; using NUnit.Framework;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.IntegrationTests.Tests namespace Content.IntegrationTests.Tests
{ {
[TestFixture] [TestFixture]
[TestOf(typeof(InventoryHelpers))]
public class InventoryHelpersTest : ContentIntegrationTest public class InventoryHelpersTest : ContentIntegrationTest
{ {
private const string Prototypes = @" private const string Prototypes = @"
@@ -22,6 +19,7 @@ namespace Content.IntegrationTests.Tests
id: InventoryStunnableDummy id: InventoryStunnableDummy
components: components:
- type: Inventory - type: Inventory
- type: ContainerContainer
- type: StatusEffects - type: StatusEffects
allowed: allowed:
- Stun - Stun
@@ -53,43 +51,41 @@ namespace Content.IntegrationTests.Tests
var sEntities = server.ResolveDependency<IEntityManager>(); var sEntities = server.ResolveDependency<IEntityManager>();
EntityUid human = default;
InventoryComponent inventory = null;
await server.WaitAssertion(() => await server.WaitAssertion(() =>
{ {
var mapMan = IoCManager.Resolve<IMapManager>(); var mapMan = IoCManager.Resolve<IMapManager>();
var systemMan = IoCManager.Resolve<IEntitySystemManager>();
mapMan.CreateNewMapEntity(MapId.Nullspace); mapMan.CreateNewMapEntity(MapId.Nullspace);
human = sEntities.SpawnEntity("InventoryStunnableDummy", MapCoordinates.Nullspace); var human = sEntities.SpawnEntity("InventoryStunnableDummy", MapCoordinates.Nullspace);
inventory = sEntities.GetComponent<InventoryComponent>(human); var invSystem = systemMan.GetEntitySystem<InventorySystem>();
// Can't do the test if this human doesn't have the slots for it. // Can't do the test if this human doesn't have the slots for it.
Assert.That(inventory.HasSlot(Slots.INNERCLOTHING)); Assert.That(invSystem.HasSlot(human, "jumpsuit"));
Assert.That(inventory.HasSlot(Slots.IDCARD)); Assert.That(invSystem.HasSlot(human, "id"));
Assert.That(inventory.SpawnItemInSlot(Slots.INNERCLOTHING, "InventoryJumpsuitJanitorDummy", true)); Assert.That(invSystem.SpawnItemInSlot(human, "jumpsuit", "InventoryJumpsuitJanitorDummy", true));
// Do we actually have the uniform equipped? // Do we actually have the uniform equipped?
Assert.That(inventory.TryGetSlotItem(Slots.INNERCLOTHING, out ItemComponent uniform)); Assert.That(invSystem.TryGetSlotEntity(human, "jumpsuit", out var uniform));
Assert.That(sEntities.GetComponent<MetaDataComponent>(uniform.Owner).EntityPrototype is Assert.That(sEntities.GetComponent<MetaDataComponent>(uniform.Value).EntityPrototype is
{ {
ID: "InventoryJumpsuitJanitorDummy" ID: "InventoryJumpsuitJanitorDummy"
}); });
EntitySystem.Get<StunSystem>().TryStun(human, TimeSpan.FromSeconds(1f), true); systemMan.GetEntitySystem<StunSystem>().TryStun(human, TimeSpan.FromSeconds(1f), true);
// Since the mob is stunned, they can't equip this. // Since the mob is stunned, they can't equip this.
Assert.That(inventory.SpawnItemInSlot(Slots.IDCARD, "InventoryIDCardDummy", true), Is.False); Assert.That(invSystem.SpawnItemInSlot(human, "id", "InventoryIDCardDummy", true), Is.False);
// Make sure we don't have the ID card equipped. // Make sure we don't have the ID card equipped.
Assert.That(inventory.TryGetSlotItem(Slots.IDCARD, out ItemComponent _), Is.False); Assert.That(invSystem.TryGetSlotEntity(human, "item", out _), Is.False);
// Let's try skipping the interaction check and see if it equips it! // Let's try skipping the interaction check and see if it equips it!
Assert.That(inventory.SpawnItemInSlot(Slots.IDCARD, "InventoryIDCardDummy")); Assert.That(invSystem.SpawnItemInSlot(human, "id", "InventoryIDCardDummy", true, true));
Assert.That(inventory.TryGetSlotItem(Slots.IDCARD, out ItemComponent id)); Assert.That(invSystem.TryGetSlotEntity(human, "id", out var idUid));
Assert.That(sEntities.GetComponent<MetaDataComponent>(id.Owner).EntityPrototype is Assert.That(sEntities.GetComponent<MetaDataComponent>(idUid.Value).EntityPrototype is
{ {
ID: "InventoryIDCardDummy" ID: "InventoryIDCardDummy"
}); });

View File

@@ -1,11 +1,11 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.PDA; using Content.Server.PDA;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.PDA; using Content.Shared.PDA;
using NUnit.Framework; using NUnit.Framework;
using Robust.Server.Player; using Robust.Server.Player;
@@ -58,6 +58,8 @@ namespace Content.IntegrationTests.Tests.PDA
var sPlayerManager = server.ResolveDependency<IPlayerManager>(); var sPlayerManager = server.ResolveDependency<IPlayerManager>();
var sEntityManager = server.ResolveDependency<IEntityManager>(); var sEntityManager = server.ResolveDependency<IEntityManager>();
var invSystem = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<InventorySystem>();
await server.WaitAssertion(() => await server.WaitAssertion(() =>
{ {
var player = sPlayerManager.Sessions.Single().AttachedEntity.GetValueOrDefault(); var player = sPlayerManager.Sessions.Single().AttachedEntity.GetValueOrDefault();
@@ -71,7 +73,7 @@ namespace Content.IntegrationTests.Tests.PDA
// Put PDA in hand // Put PDA in hand
var dummyPda = sEntityManager.SpawnEntity(PdaDummy, sEntityManager.GetComponent<TransformComponent>(player).MapPosition); var dummyPda = sEntityManager.SpawnEntity(PdaDummy, sEntityManager.GetComponent<TransformComponent>(player).MapPosition);
var pdaItemComponent = sEntityManager.GetComponent<ItemComponent>(dummyPda); var pdaItemComponent = sEntityManager.GetComponent<SharedItemComponent>(dummyPda);
sEntityManager.GetComponent<HandsComponent>(player).PutInHand(pdaItemComponent); sEntityManager.GetComponent<HandsComponent>(player).PutInHand(pdaItemComponent);
var pdaComponent = sEntityManager.GetComponent<PDAComponent>(dummyPda); var pdaComponent = sEntityManager.GetComponent<PDAComponent>(dummyPda);
@@ -91,7 +93,7 @@ namespace Content.IntegrationTests.Tests.PDA
// Put ID card in hand // Put ID card in hand
var idDummy = sEntityManager.SpawnEntity(IdCardDummy, sEntityManager.GetComponent<TransformComponent>(player).MapPosition); var idDummy = sEntityManager.SpawnEntity(IdCardDummy, sEntityManager.GetComponent<TransformComponent>(player).MapPosition);
var idItemComponent = sEntityManager.GetComponent<ItemComponent>(idDummy); var idItemComponent = sEntityManager.GetComponent<SharedItemComponent>(idDummy);
sEntityManager.GetComponent<HandsComponent>(player).PutInHand(idItemComponent); sEntityManager.GetComponent<HandsComponent>(player).PutInHand(idItemComponent);
var idCardComponent = sEntityManager.GetComponent<IdCardComponent>(idDummy); var idCardComponent = sEntityManager.GetComponent<IdCardComponent>(idDummy);
@@ -103,20 +105,16 @@ namespace Content.IntegrationTests.Tests.PDA
Assert.That(id, Is.EqualTo(idCardComponent)); Assert.That(id, Is.EqualTo(idCardComponent));
// Remove all IDs and PDAs // Remove all IDs and PDAs
var inventory = sEntityManager.GetComponent<InventoryComponent>(player); Assert.That(invSystem.TryGetSlots(player, out var slots));
foreach (var slot in inventory.Slots) foreach (var slot in slots)
{ {
var item = inventory.GetSlotItem(slot); if(!invSystem.TryGetSlotEntity(player, slot.Name, out var item))
if (item == null)
{
continue; continue;
}
if (sEntityManager.HasComponent<PDAComponent>(item.Owner)) if (sEntityManager.HasComponent<PDAComponent>(item))
{ {
inventory.ForceUnequip(slot); invSystem.TryUnequip(player, slot.Name, force: true);
} }
} }

View File

@@ -1,7 +1,7 @@
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Interaction; using Content.Server.Interaction;
using Content.Server.Items;
using Content.Shared.Interaction.Helpers; using Content.Shared.Interaction.Helpers;
using Content.Shared.Item;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -25,7 +25,7 @@ namespace Content.Server.AI.Operators.Inventory
var entMan = IoCManager.Resolve<IEntityManager>(); var entMan = IoCManager.Resolve<IEntityManager>();
if (entMan.Deleted(_target) if (entMan.Deleted(_target)
|| !entMan.HasComponent<ItemComponent>(_target) || !entMan.HasComponent<SharedItemComponent>(_target)
|| _target.IsInContainer() || _target.IsInContainer()
|| !_owner.InRangeUnobstructed(_target, popup: true)) || !_owner.InRangeUnobstructed(_target, popup: true))
{ {

View File

@@ -1,5 +1,5 @@
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items; using Content.Shared.Item;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -29,7 +29,7 @@ namespace Content.Server.AI.Operators.Inventory
return Outcome.Failed; return Outcome.Failed;
} }
if (!entMan.TryGetComponent(_target, out ItemComponent? itemComponent)) if (!entMan.TryGetComponent(_target, out SharedItemComponent? itemComponent))
{ {
return Outcome.Failed; return Outcome.Failed;
} }

View File

@@ -1,7 +1,7 @@
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Nutrition.Components; using Content.Server.Nutrition.Components;
using Content.Server.Nutrition.EntitySystems; using Content.Server.Nutrition.EntitySystems;
using Content.Shared.Item;
using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.Components;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -34,7 +34,7 @@ namespace Content.Server.AI.Operators.Nutrition
// TODO: Also have this check storage a la backpack etc. // TODO: Also have this check storage a la backpack etc.
if (entities.Deleted(_target) || if (entities.Deleted(_target) ||
!entities.TryGetComponent(_owner, out HandsComponent? handsComponent) || !entities.TryGetComponent(_owner, out HandsComponent? handsComponent) ||
!entities.TryGetComponent(_target, out ItemComponent? itemComponent)) !entities.TryGetComponent(_target, out SharedItemComponent? itemComponent))
{ {
return Outcome.Failed; return Outcome.Failed;
} }

View File

@@ -1,6 +1,6 @@
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Nutrition.Components; using Content.Server.Nutrition.Components;
using Content.Shared.Item;
using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.Components;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -33,7 +33,7 @@ namespace Content.Server.AI.Operators.Nutrition
// TODO: Also have this check storage a la backpack etc. // TODO: Also have this check storage a la backpack etc.
if (entities.Deleted(_target) || if (entities.Deleted(_target) ||
!entities.TryGetComponent(_owner, out HandsComponent? handsComponent) || !entities.TryGetComponent(_owner, out HandsComponent? handsComponent) ||
!entities.TryGetComponent(_target, out ItemComponent? itemComponent)) !entities.TryGetComponent(_target, out SharedItemComponent? itemComponent))
{ {
return Outcome.Failed; return Outcome.Failed;
} }

View File

@@ -10,7 +10,7 @@ namespace Content.Server.AI.Utility.Considerations.Clothing
{ {
public sealed class ClothingInInventoryCon : Consideration public sealed class ClothingInInventoryCon : Consideration
{ {
public ClothingInInventoryCon Slot(EquipmentSlotDefines.SlotFlags slotFlags, Blackboard context) public ClothingInInventoryCon Slot(SlotFlags slotFlags, Blackboard context)
{ {
// Ideally we'd just use a variable but then if we were iterating through multiple AI at once it'd be // Ideally we'd just use a variable but then if we were iterating through multiple AI at once it'd be
// Stuffed so we need to store it on the AI's context. // Stuffed so we need to store it on the AI's context.
@@ -21,16 +21,17 @@ namespace Content.Server.AI.Utility.Considerations.Clothing
protected override float GetScore(Blackboard context) protected override float GetScore(Blackboard context)
{ {
var slots = context.GetState<ClothingSlotConState>().GetValue(); var slots = context.GetState<ClothingSlotConState>().GetValue();
var slotFlags = EquipmentSlotDefines.SlotMasks[slots]; if (slots == null) return 0.0f;
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothingComponent)) if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothingComponent) ||
!EntitySystem.Get<InventorySystem>().TryGetSlot(entity, slots, out var slotDef))
{ {
continue; continue;
} }
if ((clothingComponent.SlotFlags & slotFlags) != 0) if ((clothingComponent.SlotFlags & slotDef.SlotFlags) != 0)
{ {
return 1.0f; return 1.0f;
} }

View File

@@ -7,7 +7,7 @@ namespace Content.Server.AI.Utility.Considerations.Clothing
public class ClothingInSlotCon : Consideration public class ClothingInSlotCon : Consideration
{ {
public ClothingInSlotCon Slot(EquipmentSlotDefines.Slots slot, Blackboard context) public ClothingInSlotCon Slot(string slot, Blackboard context)
{ {
context.GetState<ClothingSlotConState>().SetValue(slot); context.GetState<ClothingSlotConState>().SetValue(slot);
return this; return this;
@@ -17,7 +17,7 @@ namespace Content.Server.AI.Utility.Considerations.Clothing
{ {
var slot = context.GetState<ClothingSlotConState>().GetValue(); var slot = context.GetState<ClothingSlotConState>().GetValue();
var inventory = context.GetState<EquippedClothingState>().GetValue(); var inventory = context.GetState<EquippedClothingState>().GetValue();
return inventory.ContainsKey(slot) ? 1.0f : 0.0f; return slot != null && inventory.ContainsKey(slot) ? 1.0f : 0.0f;
} }
} }
} }

View File

@@ -2,7 +2,7 @@ using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Hands; using Content.Server.AI.WorldState.States.Hands;
using Content.Server.AI.WorldState.States.Inventory; using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.Items; using Content.Shared.Item;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -16,7 +16,7 @@ namespace Content.Server.AI.Utility.Considerations.Inventory
// If not then check if we have a free hand // If not then check if we have a free hand
var target = context.GetState<TargetEntityState>().GetValue(); var target = context.GetState<TargetEntityState>().GetValue();
if (target == null || !IoCManager.Resolve<IEntityManager>().HasComponent<ItemComponent>(target)) if (target == null || !IoCManager.Resolve<IEntityManager>().HasComponent<SharedItemComponent>(target))
{ {
return 0.0f; return 0.0f;
} }

View File

@@ -1,7 +1,7 @@
using Content.Server.AI.WorldState; using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory; using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.Items; using Content.Shared.Item;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -13,7 +13,7 @@ namespace Content.Server.AI.Utility.Considerations.Inventory
{ {
var target = context.GetState<TargetEntityState>().GetValue(); var target = context.GetState<TargetEntityState>().GetValue();
if (target == null || !IoCManager.Resolve<IEntityManager>().HasComponent<ItemComponent>(target)) if (target == null || !IoCManager.Resolve<IEntityManager>().HasComponent<SharedItemComponent>(target))
{ {
return 0.0f; return 0.0f;
} }

View File

@@ -27,7 +27,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
return new [] return new []
{ {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.GLOVES, context) considerationsManager.Get<ClothingInSlotCon>().Slot("gloves", context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
}; };
} }
@@ -39,7 +39,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.GLOVES) != 0) (clothing.SlotFlags & SlotFlags.GLOVES) != 0)
{ {
yield return new EquipGloves {Owner = owner, Target = entity, Bonus = Bonus}; yield return new EquipGloves {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -23,9 +23,9 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>(); var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[] return new[]
{ {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.GLOVES, context) considerationsManager.Get<ClothingInSlotCon>().Slot("gloves", context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.GLOVES, context) considerationsManager.Get<ClothingInInventoryCon>().Slot(SlotFlags.GLOVES, context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
}; };
} }
@@ -37,7 +37,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
foreach (var entity in context.GetState<NearbyClothingState>().GetValue()) foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.GLOVES) != 0) (clothing.SlotFlags & SlotFlags.GLOVES) != 0)
{ {
yield return new PickUpGloves {Owner = owner, Target = entity, Bonus = Bonus}; yield return new PickUpGloves {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -26,7 +26,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>(); var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[] { return new[] {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.HEAD, context) considerationsManager.Get<ClothingInSlotCon>().Slot("head", context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
}; };
} }
@@ -38,7 +38,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.HEAD) != 0) (clothing.SlotFlags & SlotFlags.HEAD) != 0)
{ {
yield return new EquipHead {Owner = owner, Target = entity, Bonus = Bonus}; yield return new EquipHead {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -23,9 +23,9 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>(); var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[] return new[]
{ {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.HEAD, context) considerationsManager.Get<ClothingInSlotCon>().Slot("head", context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.HEAD, context) considerationsManager.Get<ClothingInInventoryCon>().Slot(SlotFlags.HEAD, context)
.InverseBoolCurve(context) .InverseBoolCurve(context)
}; };
} }
@@ -37,7 +37,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
foreach (var entity in context.GetState<NearbyClothingState>().GetValue()) foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.HEAD) != 0) (clothing.SlotFlags & SlotFlags.HEAD) != 0)
{ {
yield return new PickUpHead {Owner = owner, Target = entity, Bonus = Bonus}; yield return new PickUpHead {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -27,7 +27,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
return new[] return new[]
{ {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context) considerationsManager.Get<ClothingInSlotCon>().Slot("outerClothing", context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
}; };
} }
@@ -39,7 +39,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.OUTERCLOTHING) != 0) (clothing.SlotFlags & SlotFlags.OUTERCLOTHING) != 0)
{ {
yield return new EquipOuterClothing {Owner = owner, Target = entity, Bonus = Bonus}; yield return new EquipOuterClothing {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -24,9 +24,9 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
return new[] return new[]
{ {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context) considerationsManager.Get<ClothingInSlotCon>().Slot("outerClothing", context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.OUTERCLOTHING, context) considerationsManager.Get<ClothingInInventoryCon>().Slot(SlotFlags.OUTERCLOTHING, context)
.InverseBoolCurve(context) .InverseBoolCurve(context)
}; };
} }
@@ -38,7 +38,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
foreach (var entity in context.GetState<NearbyClothingState>().GetValue()) foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.OUTERCLOTHING) != 0) (clothing.SlotFlags & SlotFlags.OUTERCLOTHING) != 0)
{ {
yield return new PickUpOuterClothing {Owner = owner, Target = entity, Bonus = Bonus}; yield return new PickUpOuterClothing {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -27,7 +27,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
return new[] return new[]
{ {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.SHOES, context) considerationsManager.Get<ClothingInSlotCon>().Slot("shoes", context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
}; };
} }
@@ -39,7 +39,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.SHOES) != 0) (clothing.SlotFlags & SlotFlags.FEET) != 0)
{ {
yield return new EquipShoes {Owner = owner, Target = entity, Bonus = Bonus}; yield return new EquipShoes {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -24,9 +24,9 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
return new[] return new[]
{ {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.SHOES, context) considerationsManager.Get<ClothingInSlotCon>().Slot("shoes", context)
.InverseBoolCurve(context), .InverseBoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.SHOES, context) considerationsManager.Get<ClothingInInventoryCon>().Slot(SlotFlags.FEET, context)
.InverseBoolCurve(context) .InverseBoolCurve(context)
}; };
} }
@@ -38,7 +38,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
foreach (var entity in context.GetState<NearbyClothingState>().GetValue()) foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.SHOES) != 0) (clothing.SlotFlags & SlotFlags.FEET) != 0)
{ {
yield return new PickUpShoes {Owner = owner, Target = entity, Bonus = Bonus}; yield return new PickUpShoes {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -1,13 +1,11 @@
using Content.Shared.Inventory;
namespace Content.Server.AI.WorldState.States.Clothing namespace Content.Server.AI.WorldState.States.Clothing
{ {
public sealed class ClothingSlotConState : PlanningStateData<EquipmentSlotDefines.Slots> public sealed class ClothingSlotConState : PlanningStateData<string>
{ {
public override string Name => "ClothingSlotCon"; public override string Name => "ClothingSlotCon";
public override void Reset() public override void Reset()
{ {
Value = EquipmentSlotDefines.Slots.NONE; Value = "";
} }
} }
} }

View File

@@ -2,12 +2,12 @@ using Content.Shared.Inventory;
namespace Content.Server.AI.WorldState.States.Clothing namespace Content.Server.AI.WorldState.States.Clothing
{ {
public sealed class ClothingSlotFlagConState : PlanningStateData<EquipmentSlotDefines.SlotFlags> public sealed class ClothingSlotFlagConState : PlanningStateData<SlotFlags>
{ {
public override string Name => "ClothingSlotFlagCon"; public override string Name => "ClothingSlotFlagCon";
public override void Reset() public override void Reset()
{ {
Value = EquipmentSlotDefines.SlotFlags.NONE; Value = SlotFlags.NONE;
} }
} }
} }

View File

@@ -1,34 +1,35 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.Inventory.Components;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using InventoryComponent = Content.Shared.Inventory.InventoryComponent;
namespace Content.Server.AI.WorldState.States.Clothing namespace Content.Server.AI.WorldState.States.Clothing
{ {
[UsedImplicitly] [UsedImplicitly]
public sealed class EquippedClothingState : StateData<Dictionary<EquipmentSlotDefines.Slots, EntityUid>> public sealed class EquippedClothingState : StateData<Dictionary<string, EntityUid>>
{ {
public override string Name => "EquippedClothing"; public override string Name => "EquippedClothing";
public override Dictionary<EquipmentSlotDefines.Slots, EntityUid> GetValue() public override Dictionary<string, EntityUid> GetValue()
{ {
var result = new Dictionary<EquipmentSlotDefines.Slots, EntityUid>(); var result = new Dictionary<string, EntityUid>();
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(Owner, out InventoryComponent? inventoryComponent)) var invSystem = EntitySystem.Get<InventorySystem>();
if (!invSystem.TryGetSlots(Owner, out var slotDefinitions))
{ {
return result; return result;
} }
foreach (var slot in EquipmentSlotDefines.AllSlots) foreach (var slot in slotDefinitions)
{ {
if (!inventoryComponent.HasSlot(slot)) continue; if (!invSystem.HasSlot(Owner, slot.Name)) continue;
var slotItem = inventoryComponent.GetSlotItem(slot);
if (slotItem != null) if (invSystem.TryGetSlotEntity(Owner, slot.Name, out var entityUid))
{ {
result.Add(slot, slotItem.Owner); result.Add(slot.Name, entityUid.Value);
} }
} }

View File

@@ -2,13 +2,13 @@ using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.NodeContainer; using Content.Server.NodeContainer;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.UserInterface; using Content.Server.UserInterface;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
using Content.Shared.AME; using Content.Shared.AME;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Sound; using Content.Shared.Sound;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
@@ -245,7 +245,7 @@ namespace Content.Server.AME.Components
_jarSlot.Remove(jar); _jarSlot.Remove(jar);
UpdateUserInterface(); UpdateUserInterface();
if (!_entities.TryGetComponent<HandsComponent?>(user, out var hands) || !_entities.TryGetComponent<ItemComponent?>(jar, out var item)) if (!_entities.TryGetComponent<HandsComponent?>(user, out var hands) || !_entities.TryGetComponent<SharedItemComponent?>(jar, out var item))
return; return;
if (hands.CanPutInHand(item)) if (hands.CanPutInHand(item))
hands.PutInHand(item); hands.PutInHand(item);

View File

@@ -1,18 +1,19 @@
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.PDA;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.PDA;
using Robust.Shared.IoC;
namespace Content.Server.Access.Systems namespace Content.Server.Access.Systems
{ {
public class IdCardSystem : SharedIdCardSystem public class IdCardSystem : SharedIdCardSystem
{ {
[Dependency] private readonly InventorySystem _inventorySystem = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -101,7 +102,12 @@ namespace Content.Server.Access.Systems
return true; return true;
// check inventory slot? // check inventory slot?
return TryGetIdCardSlot(uid, out idCard); if (_inventorySystem.TryGetSlotEntity(uid, "id", out var idUid) && TryGetIdCard(idUid.Value, out idCard))
{
return true;
}
return false;
} }
/// <summary> /// <summary>
@@ -121,17 +127,5 @@ namespace Content.Server.Access.Systems
return false; return false;
} }
/// <summary>
/// Try get id card from mobs ID inventory slot
/// </summary>
public bool TryGetIdCardSlot(EntityUid uid, [NotNullWhen(true)] out IdCardComponent? idCard)
{
idCard = null;
return EntityManager.TryGetComponent(uid, out InventoryComponent? inventoryComponent) &&
inventoryComponent.HasSlot(EquipmentSlotDefines.Slots.IDCARD) &&
inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent? item) &&
TryGetIdCard(item.Owner, out idCard);
}
} }
} }

View File

@@ -1,9 +1,9 @@
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
using Content.Shared.Actions.Behaviors; using Content.Shared.Actions.Behaviors;
using Content.Shared.Cooldown; using Content.Shared.Cooldown;
using Content.Shared.Item;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Sound; using Content.Shared.Sound;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -57,9 +57,9 @@ namespace Content.Server.Actions.Spells
// TODO: Look this is shitty and ideally a test would do it // TODO: Look this is shitty and ideally a test would do it
var spawnedProto = entMan.SpawnEntity(ItemProto, entMan.GetComponent<TransformComponent>(caster).MapPosition); var spawnedProto = entMan.SpawnEntity(ItemProto, entMan.GetComponent<TransformComponent>(caster).MapPosition);
if (!entMan.TryGetComponent(spawnedProto, out ItemComponent? itemComponent)) if (!entMan.TryGetComponent(spawnedProto, out SharedItemComponent? itemComponent))
{ {
Logger.Error($"Tried to use {nameof(GiveItemSpell)} but prototype has no {nameof(ItemComponent)}?"); Logger.Error($"Tried to use {nameof(GiveItemSpell)} but prototype has no {nameof(SharedItemComponent)}?");
entMan.DeleteEntity(spawnedProto); entMan.DeleteEntity(spawnedProto);
return; return;
} }

View File

@@ -10,7 +10,7 @@ using Content.Server.Disposal.Tube.Components;
using Content.Server.EUI; using Content.Server.EUI;
using Content.Server.Explosion.EntitySystems; using Content.Server.Explosion.EntitySystems;
using Content.Server.Ghost.Roles; using Content.Server.Ghost.Roles;
using Content.Server.Inventory.Components; using Content.Server.Inventory;
using Content.Server.Mind.Commands; using Content.Server.Mind.Commands;
using Content.Server.Mind.Components; using Content.Server.Mind.Components;
using Content.Server.Players; using Content.Server.Players;
@@ -19,6 +19,7 @@ using Content.Shared.Body.Components;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.GameTicking; using Content.Shared.GameTicking;
using Content.Shared.Interaction.Helpers; using Content.Shared.Interaction.Helpers;
using Content.Shared.Inventory;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using Robust.Server.Console; using Robust.Server.Console;

View File

@@ -1,7 +1,5 @@
using Content.Server.Administration.UI; using Content.Server.Administration.UI;
using Content.Server.EUI; using Content.Server.EUI;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.Preferences.Managers; using Content.Server.Preferences.Managers;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Inventory; using Content.Shared.Inventory;
@@ -15,6 +13,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using InventoryComponent = Content.Shared.Inventory.InventoryComponent;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
@@ -88,23 +87,27 @@ namespace Content.Server.Administration.Commands
profile = prefs.SelectedCharacter as HumanoidCharacterProfile; profile = prefs.SelectedCharacter as HumanoidCharacterProfile;
} }
foreach (var slot in inventoryComponent.Slots) var invSystem = EntitySystem.Get<InventorySystem>();
if (invSystem.TryGetSlots(target, out var slotDefinitions, inventoryComponent))
{ {
inventoryComponent.ForceUnequip(slot); foreach (var slot in slotDefinitions)
var gearStr = startingGear.GetGear(slot, profile);
if (gearStr == string.Empty)
{ {
continue; invSystem.TryUnequip(target, slot.Name, true, true, inventoryComponent);
} var gearStr = startingGear.GetGear(slot.Name, profile);
var equipmentEntity = entityManager.SpawnEntity(gearStr, entityManager.GetComponent<TransformComponent>(target).Coordinates); if (gearStr == string.Empty)
if (slot == EquipmentSlotDefines.Slots.IDCARD && {
entityManager.TryGetComponent<PDAComponent?>(equipmentEntity, out var pdaComponent) && continue;
pdaComponent.ContainedID != null) }
{ var equipmentEntity = entityManager.SpawnEntity(gearStr, entityManager.GetComponent<TransformComponent>(target).Coordinates);
pdaComponent.ContainedID.FullName = entityManager.GetComponent<MetaDataComponent>(target).EntityName; if (slot.Name == "id" &&
} entityManager.TryGetComponent<PDAComponent?>(equipmentEntity, out var pdaComponent) &&
pdaComponent.ContainedID != null)
{
pdaComponent.ContainedID.FullName = entityManager.GetComponent<MetaDataComponent>(target).EntityName;
}
inventoryComponent.Equip(slot, entityManager.GetComponent<ItemComponent>(equipmentEntity), false); invSystem.TryEquip(target, equipmentEntity, slot.Name, true, inventory: inventoryComponent);
}
} }
} }
} }

View File

@@ -1,5 +1,7 @@
using Content.Server.Body.Components; using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
@@ -10,7 +12,7 @@ namespace Content.Server.Atmos.Components
/// Used in internals as breath tool. /// Used in internals as breath tool.
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent]
public class BreathToolComponent : Component, IEquipped, IUnequipped public class BreathToolComponent : Component
{ {
[Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IEntityManager _entities = default!;
@@ -18,11 +20,11 @@ namespace Content.Server.Atmos.Components
/// Tool is functional only in allowed slots /// Tool is functional only in allowed slots
/// </summary> /// </summary>
[DataField("allowedSlots")] [DataField("allowedSlots")]
private EquipmentSlotDefines.SlotFlags _allowedSlots = EquipmentSlotDefines.SlotFlags.MASK; public SlotFlags AllowedSlots = SlotFlags.MASK;
public override string Name => "BreathMask"; public override string Name => "BreathMask";
public bool IsFunctional { get; private set; } public bool IsFunctional;
public EntityUid ConnectedInternalsEntity { get; private set; } public EntityUid ConnectedInternalsEntity;
protected override void Shutdown() protected override void Shutdown()
{ {
@@ -30,23 +32,6 @@ namespace Content.Server.Atmos.Components
DisconnectInternals(); DisconnectInternals();
} }
void IEquipped.Equipped(EquippedEventArgs eventArgs)
{
if ((EquipmentSlotDefines.SlotMasks[eventArgs.Slot] & _allowedSlots) != _allowedSlots) return;
IsFunctional = true;
if (_entities.TryGetComponent(eventArgs.User, out InternalsComponent? internals))
{
ConnectedInternalsEntity = eventArgs.User;
internals.ConnectBreathTool(Owner);
}
}
void IUnequipped.Unequipped(UnequippedEventArgs eventArgs)
{
DisconnectInternals();
}
public void DisconnectInternals() public void DisconnectInternals()
{ {
var old = ConnectedInternalsEntity; var old = ConnectedInternalsEntity;

View File

@@ -7,6 +7,7 @@ using Content.Server.Popups;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Body.Components; using Content.Shared.Body.Components;
using Content.Shared.Body.Events; using Content.Shared.Body.Events;
using Content.Shared.Inventory.Events;
using Content.Shared.MobState.Components; using Content.Shared.MobState.Components;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -27,6 +28,26 @@ public class LungSystem : EntitySystem
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<LungComponent, AddedToBodyEvent>(OnAddedToBody); SubscribeLocalEvent<LungComponent, AddedToBodyEvent>(OnAddedToBody);
SubscribeLocalEvent<BreathToolComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<BreathToolComponent, GotUnequippedEvent>(OnGotUnequipped);
}
private void OnGotUnequipped(EntityUid uid, BreathToolComponent component, GotUnequippedEvent args)
{
component.DisconnectInternals();
}
private void OnGotEquipped(EntityUid uid, BreathToolComponent component, GotEquippedEvent args)
{
if ((args.SlotFlags & component.AllowedSlots) != component.AllowedSlots) return;
component.IsFunctional = true;
if (TryComp(args.Equipee, out InternalsComponent? internals))
{
component.ConnectedInternalsEntity = args.Equipee;
internals.ConnectBreathTool(uid);
}
} }
private void OnAddedToBody(EntityUid uid, LungComponent component, AddedToBodyEvent args) private void OnAddedToBody(EntityUid uid, LungComponent component, AddedToBodyEvent args)

View File

@@ -1,17 +1,16 @@
using System.Linq; using System.Linq;
using Content.Server.Act; using Content.Server.Act;
using Content.Server.Administration;
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.Chat.Managers; using Content.Server.Chat.Managers;
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Players; using Content.Server.Players;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes; using Content.Shared.Damage.Prototypes;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Item;
using Content.Shared.Popups; using Content.Shared.Popups;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Console; using Robust.Shared.Console;
@@ -108,7 +107,7 @@ namespace Content.Server.Chat.Commands
{ {
foreach (var entity in entities) foreach (var entity in entities)
{ {
if (_entities.HasComponent<ItemComponent>(entity)) if (_entities.HasComponent<SharedItemComponent>(entity))
continue; continue;
var suicide = _entities.GetComponents<ISuicideAct>(entity).FirstOrDefault(); var suicide = _entities.GetComponents<ISuicideAct>(entity).FirstOrDefault();
if (suicide != null) if (suicide != null)

View File

@@ -3,8 +3,6 @@ using System.Linq;
using Content.Server.Administration.Managers; using Content.Server.Administration.Managers;
using Content.Server.Ghost.Components; using Content.Server.Ghost.Components;
using Content.Server.Headset; using Content.Server.Headset;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.MoMMI; using Content.Server.MoMMI;
using Content.Server.Preferences.Managers; using Content.Server.Preferences.Managers;
using Content.Server.Radio.EntitySystems; using Content.Server.Radio.EntitySystems;
@@ -171,9 +169,10 @@ namespace Content.Server.Chat.Managers
message = message[0].ToString().ToUpper() + message = message[0].ToString().ToUpper() +
message.Remove(0, 1); message.Remove(0, 1);
if (_entManager.TryGetComponent(source, out InventoryComponent? inventory) && var invSystem = EntitySystem.Get<InventorySystem>();
inventory.TryGetSlotItem(EquipmentSlotDefines.Slots.EARS, out ItemComponent? item) &&
_entManager.TryGetComponent(item.Owner, out HeadsetComponent? headset)) if (invSystem.TryGetSlotEntity(source, "ears", out var entityUid) &&
_entManager.TryGetComponent(entityUid, out HeadsetComponent? headset))
{ {
headset.RadioRequested = true; headset.RadioRequested = true;
} }

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Labels.Components; using Content.Server.Labels.Components;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.UserInterface; using Content.Server.UserInterface;
@@ -12,6 +11,7 @@ using Content.Shared.Chemistry.Components;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Random.Helpers; using Content.Shared.Random.Helpers;
using Content.Shared.Sound; using Content.Shared.Sound;
@@ -319,7 +319,7 @@ namespace Content.Server.Chemistry.Components
//Try to give them the bottle //Try to give them the bottle
if (_entities.TryGetComponent<HandsComponent?>(user, out var hands) && if (_entities.TryGetComponent<HandsComponent?>(user, out var hands) &&
_entities.TryGetComponent<ItemComponent?>(bottle, out var item)) _entities.TryGetComponent<SharedItemComponent?>(bottle, out var item))
{ {
if (hands.CanPutInHand(item)) if (hands.CanPutInHand(item))
{ {
@@ -368,7 +368,7 @@ namespace Content.Server.Chemistry.Components
//Try to give them the bottle //Try to give them the bottle
if (_entities.TryGetComponent<HandsComponent?>(user, out var hands) && if (_entities.TryGetComponent<HandsComponent?>(user, out var hands) &&
_entities.TryGetComponent<ItemComponent?>(pill, out var item)) _entities.TryGetComponent<SharedItemComponent?>(pill, out var item))
{ {
if (hands.CanPutInHand(item)) if (hands.CanPutInHand(item))
{ {

View File

@@ -1,8 +1,6 @@
using Content.Server.Body.Components; using Content.Server.Body.Components;
using Content.Server.Body.Systems; using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Foam; using Content.Shared.Foam;
using Content.Shared.Inventory; using Content.Shared.Inventory;
@@ -40,20 +38,22 @@ namespace Content.Server.Chemistry.Components
if (!_entMan.TryGetComponent(entity, out BloodstreamComponent? bloodstream)) if (!_entMan.TryGetComponent(entity, out BloodstreamComponent? bloodstream))
return; return;
var invSystem = EntitySystem.Get<InventorySystem>();
// TODO: Add a permeability property to clothing // TODO: Add a permeability property to clothing
// For now it just adds to protection for each clothing equipped // For now it just adds to protection for each clothing equipped
var protection = 0f; var protection = 0f;
if (_entMan.TryGetComponent(entity, out InventoryComponent? inventory)) if (invSystem.TryGetSlots(entity, out var slotDefinitions))
{ {
foreach (var slot in inventory.Slots) foreach (var slot in slotDefinitions)
{ {
if (slot == EquipmentSlotDefines.Slots.BACKPACK || if (slot.Name == "back" ||
slot == EquipmentSlotDefines.Slots.POCKET1 || slot.Name == "pocket1" ||
slot == EquipmentSlotDefines.Slots.POCKET2 || slot.Name == "pocket2" ||
slot == EquipmentSlotDefines.Slots.IDCARD) slot.Name == "id")
continue; continue;
if (inventory.TryGetSlotItem(slot, out ItemComponent? _)) if (invSystem.TryGetSlotEntity(entity, slot.Name, out _))
protection += 0.025f; protection += 0.025f;
} }
} }

View File

@@ -1,94 +1,67 @@
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Shared.Clothing; using Content.Shared.Clothing;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared.Item; using Content.Shared.Item;
using Content.Shared.Popups;
using Content.Shared.Sound;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Server.Clothing.Components namespace Content.Server.Clothing.Components
{ {
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(SharedItemComponent))] [ComponentReference(typeof(SharedItemComponent))]
[ComponentReference(typeof(ItemComponent))] public class ItemComponent : SharedItemComponent{}
[NetworkedComponent()]
[RegisterComponent]
[NetworkedComponent]
[ComponentReference(typeof(SharedItemComponent))]
public class ClothingComponent : ItemComponent, IUse public class ClothingComponent : ItemComponent, IUse
{ {
[Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IEntityManager _entities = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
public override string Name => "Clothing"; public override string Name => "Clothing";
[ViewVariables]
[DataField("Slots")]
public SlotFlags SlotFlags = SlotFlags.PREVENTEQUIP; //Different from None, NONE allows equips if no slot flags are required
[DataField("QuickEquip")] [DataField("QuickEquip")]
private bool _quickEquipEnabled = true; private bool _quickEquipEnabled = true;
[DataField("HeatResistance")] [DataField("HeatResistance")]
private int _heatResistance = 323; private int _heatResistance = 323;
[DataField("EquipSound")]
public SoundSpecifier? EquipSound { get; set; } = default!;
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public int HeatResistance => _heatResistance; public int HeatResistance => _heatResistance;
[DataField("ClothingPrefix")]
private string? _clothingEquippedPrefix;
[ViewVariables(VVAccess.ReadWrite)]
public string? ClothingEquippedPrefix
{
get => _clothingEquippedPrefix;
set
{
Dirty();
_clothingEquippedPrefix = value;
}
}
public override ComponentState GetComponentState()
{
return new ClothingComponentState(ClothingEquippedPrefix, EquippedPrefix);
}
bool IUse.UseEntity(UseEntityEventArgs eventArgs) bool IUse.UseEntity(UseEntityEventArgs eventArgs)
{ {
if (!_quickEquipEnabled) return false; if (!_quickEquipEnabled) return false;
var invSystem = EntitySystem.Get<InventorySystem>();
if (!_entities.TryGetComponent(eventArgs.User, out InventoryComponent? inv) if (!_entities.TryGetComponent(eventArgs.User, out InventoryComponent? inv)
|| !_entities.TryGetComponent(eventArgs.User, out HandsComponent? hands)) return false; || !_entities.TryGetComponent(eventArgs.User, out HandsComponent? hands) || !_prototype.TryIndex<InventoryTemplatePrototype>(inv.TemplateId, out var prototype)) return false;
foreach (var (slot, flag) in SlotMasks) foreach (var slotDef in prototype.Slots)
{ {
// We check if the clothing can be equipped in this slot. if(!invSystem.CanEquip(eventArgs.User, Owner, slotDef.Name, out _, slotDef, inv))
if ((SlotFlags & flag) == 0) continue; continue;
if (inv.TryGetSlotItem(slot, out ItemComponent? item)) if (invSystem.TryGetSlotEntity(eventArgs.User, slotDef.Name, out var slotEntity, inv))
{ {
if (!inv.CanUnequip(slot)) continue; if(!invSystem.TryUnequip(eventArgs.User, slotDef.Name, true, inventory: inv))
hands.Drop(Owner); continue;
inv.Unequip(slot);
hands.PutInHand(item);
if (!TryEquip(inv, slot, eventArgs.User)) if (!invSystem.TryEquip(eventArgs.User, Owner, slotDef.Name, true, inventory: inv))
{ continue;
hands.Drop(item.Owner);
inv.Equip(slot, item); hands.PutInHandOrDrop(slotEntity.Value);
hands.PutInHand(_entities.GetComponent<ItemComponent>(Owner));
}
} }
else else
{ {
hands.Drop(Owner); if (!invSystem.TryEquip(eventArgs.User, Owner, slotDef.Name, true, inventory: inv))
if (!TryEquip(inv, slot, eventArgs.User)) continue;
hands.PutInHand(_entities.GetComponent<ItemComponent>(Owner));
} }
return true; return true;
@@ -96,18 +69,5 @@ namespace Content.Server.Clothing.Components
return false; return false;
} }
public bool TryEquip(InventoryComponent inv, Slots slot, EntityUid user)
{
if (!inv.Equip(slot, this, true, out var reason))
{
if (reason != null)
Owner.PopupMessage(user, reason);
return false;
}
return true;
}
} }
} }

View File

@@ -1,7 +1,5 @@
using Content.Server.Alert; using Content.Server.Alert;
using Content.Server.Atmos.Components; using Content.Server.Atmos.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Actions.Behaviors.Item; using Content.Shared.Actions.Behaviors.Item;
using Content.Shared.Actions.Components; using Content.Shared.Actions.Components;
@@ -9,6 +7,7 @@ using Content.Shared.Alert;
using Content.Shared.Clothing; using Content.Shared.Clothing;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Item;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Containers; using Robust.Shared.Containers;
@@ -16,15 +15,14 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Server.Clothing.Components namespace Content.Server.Clothing.Components
{ {
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(IActivate))] [ComponentReference(typeof(IActivate))]
public sealed class MagbootsComponent : SharedMagbootsComponent, IUnequipped, IEquipped, IUse, IActivate public sealed class MagbootsComponent : SharedMagbootsComponent, IUse, IActivate
{ {
[ComponentDependency] private ItemComponent? _item = null; [ComponentDependency] private SharedItemComponent? _item = null;
[ComponentDependency] private ItemActionsComponent? _itemActions = null; [ComponentDependency] private ItemActionsComponent? _itemActions = null;
[ComponentDependency] private SpriteComponent? _sprite = null; [ComponentDependency] private SpriteComponent? _sprite = null;
@@ -40,7 +38,12 @@ namespace Content.Server.Clothing.Components
{ {
_on = value; _on = value;
UpdateContainer(); if (Owner.TryGetContainer(out var container) && EntitySystem.Get<InventorySystem>()
.TryGetSlotEntity(container.Owner, "shoes", out var entityUid) && entityUid == Owner)
{
EntitySystem.Get<MagbootsSystem>().UpdateMagbootEffects(container.Owner, Owner, true, this);
}
_itemActions?.Toggle(ItemActionType.ToggleMagboots, On); _itemActions?.Toggle(ItemActionType.ToggleMagboots, On);
if (_item != null) if (_item != null)
_item.EquippedPrefix = On ? "on" : null; _item.EquippedPrefix = On ? "on" : null;
@@ -55,54 +58,6 @@ namespace Content.Server.Clothing.Components
On = !On; On = !On;
} }
void IUnequipped.Unequipped(UnequippedEventArgs eventArgs)
{
if (On && eventArgs.Slot == Slots.SHOES)
{
if (_entMan.TryGetComponent(eventArgs.User, out MovedByPressureComponent? movedByPressure))
{
movedByPressure.Enabled = true;
}
if (_entMan.TryGetComponent(eventArgs.User, out ServerAlertsComponent? alerts))
{
alerts.ClearAlert(AlertType.Magboots);
}
}
}
void IEquipped.Equipped(EquippedEventArgs eventArgs)
{
UpdateContainer();
}
private void UpdateContainer()
{
if (!Owner.TryGetContainer(out var container))
return;
if (_entMan.TryGetComponent(container.Owner, out InventoryComponent? inventoryComponent)
&& inventoryComponent.GetSlotItem(Slots.SHOES)?.Owner == Owner)
{
if (_entMan.TryGetComponent(container.Owner, out MovedByPressureComponent? movedByPressure))
{
movedByPressure.Enabled = false;
}
if (_entMan.TryGetComponent(container.Owner, out ServerAlertsComponent? alerts))
{
if (On)
{
alerts.ShowAlert(AlertType.Magboots);
}
else
{
alerts.ClearAlert(AlertType.Magboots);
}
}
}
}
bool IUse.UseEntity(UseEntityEventArgs eventArgs) bool IUse.UseEntity(UseEntityEventArgs eventArgs)
{ {
Toggle(eventArgs.User); Toggle(eventArgs.User);

View File

@@ -1,4 +1,8 @@
using Content.Server.Alert;
using Content.Server.Atmos.Components;
using Content.Server.Clothing.Components; using Content.Server.Clothing.Components;
using Content.Shared.Alert;
using Content.Shared.Inventory.Events;
using Content.Shared.Movement.EntitySystems; using Content.Shared.Movement.EntitySystems;
using Content.Shared.Slippery; using Content.Shared.Slippery;
using Content.Shared.Verbs; using Content.Shared.Verbs;
@@ -16,6 +20,48 @@ namespace Content.Server.Clothing
SubscribeLocalEvent<MagbootsComponent, GetActivationVerbsEvent>(AddToggleVerb); SubscribeLocalEvent<MagbootsComponent, GetActivationVerbsEvent>(AddToggleVerb);
SubscribeLocalEvent<MagbootsComponent, SlipAttemptEvent>(OnSlipAttempt); SubscribeLocalEvent<MagbootsComponent, SlipAttemptEvent>(OnSlipAttempt);
SubscribeLocalEvent<MagbootsComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed); SubscribeLocalEvent<MagbootsComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
SubscribeLocalEvent<MagbootsComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<MagbootsComponent, GotUnequippedEvent>(OnGotUnequipped);
}
public void UpdateMagbootEffects(EntityUid parent, EntityUid uid, bool state, MagbootsComponent? component)
{
if (!Resolve(uid, ref component))
return;
state = state && component.On;
if (TryComp(parent, out MovedByPressureComponent? movedByPressure))
{
movedByPressure.Enabled = state;
}
if (TryComp(parent, out ServerAlertsComponent? alerts))
{
if (state)
{
alerts.ShowAlert(AlertType.Magboots);
}
else
{
alerts.ClearAlert(AlertType.Magboots);
}
}
}
private void OnGotUnequipped(EntityUid uid, MagbootsComponent component, GotUnequippedEvent args)
{
if (args.Slot == "shoes")
{
UpdateMagbootEffects(args.Equipee, uid, true, component);
}
}
private void OnGotEquipped(EntityUid uid, MagbootsComponent component, GotEquippedEvent args)
{
if (args.Slot == "shoes")
{
UpdateMagbootEffects(args.Equipee, uid, false, component);
}
} }
private void OnRefreshMovespeed(EntityUid uid, MagbootsComponent component, RefreshMovementSpeedModifiersEvent args) private void OnRefreshMovespeed(EntityUid uid, MagbootsComponent component, RefreshMovementSpeedModifiersEvent args)

View File

@@ -5,8 +5,6 @@ using System.Threading.Tasks;
using Content.Server.Construction.Components; using Content.Server.Construction.Components;
using Content.Server.DoAfter; using Content.Server.DoAfter;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.Storage.Components; using Content.Server.Storage.Components;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
using Content.Shared.Construction; using Content.Shared.Construction;
@@ -14,6 +12,8 @@ using Content.Shared.Construction.Prototypes;
using Content.Shared.Construction.Steps; using Content.Shared.Construction.Steps;
using Content.Shared.Coordinates; using Content.Shared.Coordinates;
using Content.Shared.Interaction.Helpers; using Content.Shared.Interaction.Helpers;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Popups; using Content.Shared.Popups;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -28,6 +28,8 @@ namespace Content.Server.Construction
public partial class ConstructionSystem public partial class ConstructionSystem
{ {
[Dependency] private readonly InventorySystem _inventorySystem = default!;
// --- WARNING! LEGACY CODE AHEAD! --- // --- WARNING! LEGACY CODE AHEAD! ---
// This entire file contains the legacy code for initial construction. // This entire file contains the legacy code for initial construction.
// This is bound to be replaced by a better alternative (probably using dummy entities) // This is bound to be replaced by a better alternative (probably using dummy entities)
@@ -61,11 +63,12 @@ namespace Content.Server.Construction
} }
} }
if (EntityManager.TryGetComponent(user!, out InventoryComponent? inventory)) if (_inventorySystem.TryGetContainerSlotEnumerator(user, out var containerSlotEnumerator))
{ {
foreach (var held in inventory.GetAllHeldItems()) while (containerSlotEnumerator.MoveNext(out var containerSlot))
{ {
if (EntityManager.TryGetComponent(held, out ServerStorageComponent? storage)) if(!containerSlot.ContainedEntity.HasValue) continue;
if (EntityManager.TryGetComponent(containerSlot.ContainedEntity.Value, out ServerStorageComponent? storage))
{ {
foreach (var storedEntity in storage.StoredEntities!) foreach (var storedEntity in storage.StoredEntities!)
{ {
@@ -73,7 +76,7 @@ namespace Content.Server.Construction
} }
} }
yield return held; yield return containerSlot.ContainedEntity.Value;
} }
} }
@@ -330,7 +333,7 @@ namespace Content.Server.Construction
} }
if (await Construct(user, "item_construction", constructionGraph, edge, targetNode) is {Valid: true} item && if (await Construct(user, "item_construction", constructionGraph, edge, targetNode) is {Valid: true} item &&
EntityManager.TryGetComponent(item, out ItemComponent? itemComp)) EntityManager.TryGetComponent(item, out SharedItemComponent? itemComp))
hands.PutInHandOrDrop(itemComp); hands.PutInHandOrDrop(itemComp);
} }

View File

@@ -1,15 +1,7 @@
using System.Collections.Generic;
using Content.Server.Items;
using Content.Server.MachineLinking.Components;
using Content.Server.Power.Components;
using Content.Shared.Conveyor; using Content.Shared.Conveyor;
using Content.Shared.MachineLinking;
using Robust.Server.GameObjects;
using Robust.Shared.Analyzers; using Robust.Shared.Analyzers;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;

View File

@@ -1,11 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.Items;
using Content.Server.MachineLinking.Events; using Content.Server.MachineLinking.Events;
using Content.Server.MachineLinking.Models; using Content.Server.MachineLinking.Models;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Stunnable; using Content.Server.Stunnable;
using Content.Shared.Conveyor; using Content.Shared.Conveyor;
using Content.Shared.Item;
using Content.Shared.MachineLinking; using Content.Shared.MachineLinking;
using Content.Shared.Movement.Components; using Content.Shared.Movement.Components;
using Content.Shared.Popups; using Content.Shared.Popups;
@@ -104,7 +104,7 @@ namespace Content.Server.Conveyor
return false; return false;
} }
if (EntityManager.HasComponent<ItemComponent>(component.Owner)) if (EntityManager.HasComponent<SharedItemComponent>(component.Owner))
{ {
return false; return false;
} }

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.Atmos; using Content.Server.Atmos;
using Content.Server.Disposal.Tube.Components; using Content.Server.Disposal.Tube.Components;
using Content.Server.Items;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Body.Components; using Content.Shared.Body.Components;
using Content.Shared.Item;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -81,7 +81,7 @@ namespace Content.Server.Disposal.Unit.Components
return false; return false;
} }
return _entMan.HasComponent<ItemComponent>(entity) || return _entMan.HasComponent<SharedItemComponent>(entity) ||
_entMan.HasComponent<SharedBodyComponent>(entity); _entMan.HasComponent<SharedBodyComponent>(entity);
} }

View File

@@ -8,13 +8,13 @@ using Content.Server.Disposal.Tube.Components;
using Content.Server.Disposal.Unit.Components; using Content.Server.Disposal.Unit.Components;
using Content.Server.DoAfter; using Content.Server.DoAfter;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Disposal; using Content.Shared.Disposal;
using Content.Shared.Disposal.Components; using Content.Shared.Disposal.Components;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Movement; using Content.Shared.Movement;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Throwing; using Content.Shared.Throwing;
@@ -369,7 +369,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
{ {
// TODO: We need to use a specific collision method (which sloth hasn't coded yet) for actual bounds overlaps. // TODO: We need to use a specific collision method (which sloth hasn't coded yet) for actual bounds overlaps.
// Check for itemcomp as we won't just block the disposal unit "sleeping" for something it can't collide with anyway. // Check for itemcomp as we won't just block the disposal unit "sleeping" for something it can't collide with anyway.
if (!EntityManager.HasComponent<ItemComponent>(uid) && body.GetWorldAABB().Intersects(disposalsBounds!.Value)) continue; if (!EntityManager.HasComponent<SharedItemComponent>(uid) && body.GetWorldAABB().Intersects(disposalsBounds!.Value)) continue;
component.RecentlyEjected.RemoveAt(i); component.RecentlyEjected.RemoveAt(i);
} }
} }

View File

@@ -1,8 +1,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items; using Content.Shared.Item;
using Content.Server.Stunnable.Components;
using Content.Shared.Stunnable; using Content.Shared.Stunnable;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -33,7 +32,7 @@ namespace Content.Server.DoAfter
// NeedHand // NeedHand
private readonly string? _activeHand; private readonly string? _activeHand;
private readonly ItemComponent? _activeItem; private readonly SharedItemComponent? _activeItem;
public DoAfter(DoAfterEventArgs eventArgs, IEntityManager entityManager) public DoAfter(DoAfterEventArgs eventArgs, IEntityManager entityManager)
{ {

View File

@@ -1,12 +1,11 @@
using Content.Server.DoAfter; using Content.Server.DoAfter;
using Content.Server.Engineering.Components; using Content.Server.Engineering.Components;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Interaction.Helpers; using Content.Shared.Interaction.Helpers;
using Content.Shared.Item;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.Engineering.EntitySystems namespace Content.Server.Engineering.EntitySystems
{ {
@@ -47,7 +46,7 @@ namespace Content.Server.Engineering.EntitySystems
var entity = EntityManager.SpawnEntity(component.Prototype, EntityManager.GetComponent<TransformComponent>(component.Owner).Coordinates); var entity = EntityManager.SpawnEntity(component.Prototype, EntityManager.GetComponent<TransformComponent>(component.Owner).Coordinates);
if (EntityManager.TryGetComponent<HandsComponent?>(args.User, out var hands) if (EntityManager.TryGetComponent<HandsComponent?>(args.User, out var hands)
&& EntityManager.TryGetComponent<ItemComponent?>(entity, out var item)) && EntityManager.TryGetComponent<SharedItemComponent?>(entity, out var item))
{ {
hands.PutInHandOrDrop(item); hands.PutInHandOrDrop(item);
} }

View File

@@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.Flash.Components; using Content.Server.Flash.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.Stunnable; using Content.Server.Stunnable;
using Content.Server.Weapon.Melee; using Content.Server.Weapon.Melee;
using Content.Shared.Examine; using Content.Shared.Examine;
@@ -20,6 +18,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using InventoryComponent = Content.Shared.Inventory.InventoryComponent;
namespace Content.Server.Flash namespace Content.Server.Flash
{ {
@@ -28,6 +27,7 @@ namespace Content.Server.Flash
[Dependency] private readonly IEntityLookup _entityLookup = default!; [Dependency] private readonly IEntityLookup _entityLookup = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly StunSystem _stunSystem = default!; [Dependency] private readonly StunSystem _stunSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -187,8 +187,8 @@ namespace Content.Server.Flash
private void OnInventoryFlashAttempt(EntityUid uid, InventoryComponent component, FlashAttemptEvent args) private void OnInventoryFlashAttempt(EntityUid uid, InventoryComponent component, FlashAttemptEvent args)
{ {
// Forward the event to the glasses, if any. // Forward the event to the glasses, if any.
if(component.TryGetSlotItem(EquipmentSlotDefines.Slots.EYES, out ItemComponent? glasses)) if(_inventorySystem.TryGetSlotEntity(uid, "eyes", out var slotEntity, component))
RaiseLocalEvent(glasses.Owner, args); RaiseLocalEvent(slotEntity.Value, args);
} }
private void OnFlashImmunityFlashAttempt(EntityUid uid, FlashImmunityComponent component, FlashAttemptEvent args) private void OnFlashImmunityFlashAttempt(EntityUid uid, FlashImmunityComponent component, FlashAttemptEvent args)

View File

@@ -6,17 +6,12 @@ using Content.Server.Access.Systems;
using Content.Server.Ghost; using Content.Server.Ghost;
using Content.Server.Ghost.Components; using Content.Server.Ghost.Components;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.PDA;
using Content.Server.Players; using Content.Server.Players;
using Content.Server.Roles; using Content.Server.Roles;
using Content.Server.Spawners.Components; using Content.Server.Spawners.Components;
using Content.Server.Speech.Components; using Content.Server.Speech.Components;
using Content.Server.Station; using Content.Server.Station;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.CharacterAppearance.Systems;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.GameTicking; using Content.Shared.GameTicking;
using Content.Shared.Ghost; using Content.Shared.Ghost;
@@ -33,7 +28,6 @@ using Robust.Shared.Map;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using static Content.Server.Station.StationSystem;
namespace Content.Server.GameTicking namespace Content.Server.GameTicking
{ {
@@ -43,6 +37,7 @@ namespace Content.Server.GameTicking
private const string ObserverPrototypeName = "MobObserver"; private const string ObserverPrototypeName = "MobObserver";
[Dependency] private readonly IdCardSystem _cardSystem = default!; [Dependency] private readonly IdCardSystem _cardSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
/// <summary> /// <summary>
/// Can't yet be removed because every test ever seems to depend on it. I'll make removing this a different PR. /// Can't yet be removed because every test ever seems to depend on it. I'll make removing this a different PR.
@@ -244,15 +239,15 @@ namespace Content.Server.GameTicking
#region Equip Helpers #region Equip Helpers
public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGear, HumanoidCharacterProfile? profile) public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGear, HumanoidCharacterProfile? profile)
{ {
if (EntityManager.TryGetComponent(entity, out InventoryComponent? inventory)) if (_inventorySystem.TryGetSlots(entity, out var slotDefinitions))
{ {
foreach (var slot in EquipmentSlotDefines.AllSlots) foreach (var slot in slotDefinitions)
{ {
var equipmentStr = startingGear.GetGear(slot, profile); var equipmentStr = startingGear.GetGear(slot.Name, profile);
if (!string.IsNullOrEmpty(equipmentStr)) if (!string.IsNullOrEmpty(equipmentStr))
{ {
var equipmentEntity = EntityManager.SpawnEntity(equipmentStr, EntityManager.GetComponent<TransformComponent>(entity).Coordinates); var equipmentEntity = EntityManager.SpawnEntity(equipmentStr, EntityManager.GetComponent<TransformComponent>(entity).Coordinates);
inventory.Equip(slot, EntityManager.GetComponent<ItemComponent>(equipmentEntity)); _inventorySystem.TryEquip(entity, equipmentEntity, slot.Name, true);
} }
} }
} }
@@ -270,17 +265,10 @@ namespace Content.Server.GameTicking
public void EquipIdCard(EntityUid entity, string characterName, JobPrototype jobPrototype) public void EquipIdCard(EntityUid entity, string characterName, JobPrototype jobPrototype)
{ {
if (!EntityManager.TryGetComponent(entity, out InventoryComponent? inventory)) if (!_inventorySystem.TryGetSlotEntity(entity, "id", out var idUid))
return; return;
if (!inventory.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent? item)) if (!EntityManager.TryGetComponent(idUid, out PDAComponent? pdaComponent) || pdaComponent.ContainedID == null)
{
return;
}
var itemEntity = item.Owner;
if (!EntityManager.TryGetComponent(itemEntity, out PDAComponent? pdaComponent) || pdaComponent.ContainedID == null)
return; return;
var card = pdaComponent.ContainedID; var card = pdaComponent.ContainedID;

View File

@@ -4,8 +4,6 @@ using System.Linq;
using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.EntitySystems;
using Content.Server.Chat.Managers; using Content.Server.Chat.Managers;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.PDA; using Content.Server.PDA;
using Content.Server.Players; using Content.Server.Players;
using Content.Server.Spawners.Components; using Content.Server.Spawners.Components;
@@ -42,6 +40,7 @@ public class TraitorDeathMatchRuleSystem : GameRuleSystem
[Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly MaxTimeRestartRuleSystem _restarter = default!; [Dependency] private readonly MaxTimeRestartRuleSystem _restarter = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
public override string Prototype => "TraitorDeathMatch"; public override string Prototype => "TraitorDeathMatch";
@@ -86,13 +85,13 @@ public class TraitorDeathMatchRuleSystem : GameRuleSystem
// Delete anything that may contain "dangerous" role-specific items. // Delete anything that may contain "dangerous" role-specific items.
// (This includes the PDA, as everybody gets the captain PDA in this mode for true-all-access reasons.) // (This includes the PDA, as everybody gets the captain PDA in this mode for true-all-access reasons.)
if (mind.OwnedEntity is {Valid: true} owned && TryComp(owned, out InventoryComponent? inventory)) if (mind.OwnedEntity is {Valid: true} owned)
{ {
var victimSlots = new[] {EquipmentSlotDefines.Slots.IDCARD, EquipmentSlotDefines.Slots.BELT, EquipmentSlotDefines.Slots.BACKPACK}; var victimSlots = new[] {"id", "belt", "back"};
foreach (var slot in victimSlots) foreach (var slot in victimSlots)
{ {
if (inventory.TryGetSlotItem(slot, out ItemComponent? vItem)) if(_inventory.TryUnequip(owned, slot, out var entityUid, true, true))
Del(vItem.Owner); Del(entityUid.Value);
} }
// Replace their items: // Replace their items:
@@ -101,15 +100,15 @@ public class TraitorDeathMatchRuleSystem : GameRuleSystem
// pda // pda
var newPDA = Spawn(PDAPrototypeName, ownedCoords); var newPDA = Spawn(PDAPrototypeName, ownedCoords);
inventory.Equip(EquipmentSlotDefines.Slots.IDCARD, Comp<ItemComponent>(newPDA)); _inventory.TryEquip(owned, newPDA, "id", true);
// belt // belt
var newTmp = Spawn(BeltPrototypeName, ownedCoords); var newTmp = Spawn(BeltPrototypeName, ownedCoords);
inventory.Equip(EquipmentSlotDefines.Slots.BELT, Comp<ItemComponent>(newTmp)); _inventory.TryEquip(owned, newTmp, "belt", true);
// backpack // backpack
newTmp = Spawn(BackpackPrototypeName, ownedCoords); newTmp = Spawn(BackpackPrototypeName, ownedCoords);
inventory.Equip(EquipmentSlotDefines.Slots.BACKPACK, Comp<ItemComponent>(newTmp)); _inventory.TryEquip(owned, newTmp, "back", true);
// Like normal traitors, they need access to a traitor account. // Like normal traitors, they need access to a traitor account.
var uplinkAccount = new UplinkAccount(startingBalance, owned); var uplinkAccount = new UplinkAccount(startingBalance, owned);

View File

@@ -1,7 +1,6 @@
using Content.Server.Actions; using Content.Server.Actions;
using Content.Server.DoAfter; using Content.Server.DoAfter;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Actions.Components; using Content.Shared.Actions.Components;
@@ -10,7 +9,6 @@ using Content.Shared.Damage;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.MobState; using Content.Shared.MobState;
using Content.Shared.MobState.EntitySystems;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Containers; using Robust.Shared.Containers;

View File

@@ -4,12 +4,12 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Server.Act; using Content.Server.Act;
using Content.Server.Interaction; using Content.Server.Interaction;
using Content.Server.Items;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Server.Pulling; using Content.Server.Pulling;
using Content.Shared.Audio; using Content.Shared.Audio;
using Content.Shared.Body.Part; using Content.Shared.Body.Part;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Item;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Pulling.Components; using Content.Shared.Pulling.Components;
using Content.Shared.Sound; using Content.Shared.Sound;
@@ -39,7 +39,7 @@ namespace Content.Server.Hands.Components
protected override void OnHeldEntityRemovedFromHand(EntityUid heldEntity, HandState handState) protected override void OnHeldEntityRemovedFromHand(EntityUid heldEntity, HandState handState)
{ {
if (_entities.TryGetComponent(heldEntity, out ItemComponent? item)) if (_entities.TryGetComponent(heldEntity, out SharedItemComponent? item))
{ {
item.RemovedFromSlot(); item.RemovedFromSlot();
_entitySystemManager.GetEntitySystem<InteractionSystem>().UnequippedHandInteraction(Owner, heldEntity, handState); _entitySystemManager.GetEntitySystem<InteractionSystem>().UnequippedHandInteraction(Owner, heldEntity, handState);
@@ -153,19 +153,19 @@ namespace Content.Server.Hands.Components
/// <summary> /// <summary>
/// Tries to get the ItemComponent on the entity held by a hand. /// Tries to get the ItemComponent on the entity held by a hand.
/// </summary> /// </summary>
public ItemComponent? GetItem(string handName) public SharedItemComponent? GetItem(string handName)
{ {
if (!TryGetHeldEntity(handName, out var heldEntity)) if (!TryGetHeldEntity(handName, out var heldEntity))
return null; return null;
_entities.TryGetComponent(heldEntity, out ItemComponent? item); _entities.TryGetComponent(heldEntity, out SharedItemComponent? item);
return item; return item;
} }
/// <summary> /// <summary>
/// Tries to get the ItemComponent on the entity held by a hand. /// Tries to get the ItemComponent on the entity held by a hand.
/// </summary> /// </summary>
public bool TryGetItem(string handName, [NotNullWhen(true)] out ItemComponent? item) public bool TryGetItem(string handName, [NotNullWhen(true)] out SharedItemComponent? item)
{ {
item = null; item = null;
@@ -178,23 +178,23 @@ namespace Content.Server.Hands.Components
/// <summary> /// <summary>
/// Tries to get the ItemComponent off the entity in the active hand. /// Tries to get the ItemComponent off the entity in the active hand.
/// </summary> /// </summary>
public ItemComponent? GetActiveHand public SharedItemComponent? GetActiveHand
{ {
get get
{ {
if (!TryGetActiveHeldEntity(out var heldEntity)) if (!TryGetActiveHeldEntity(out var heldEntity))
return null; return null;
_entities.TryGetComponent(heldEntity, out ItemComponent? item); _entities.TryGetComponent(heldEntity, out SharedItemComponent? item);
return item; return item;
} }
} }
public IEnumerable<ItemComponent> GetAllHeldItems() public IEnumerable<SharedItemComponent> GetAllHeldItems()
{ {
foreach (var entity in GetAllHeldEntities()) foreach (var entity in GetAllHeldEntities())
{ {
if (_entities.TryGetComponent(entity, out ItemComponent? item)) if (_entities.TryGetComponent(entity, out SharedItemComponent? item))
yield return item; yield return item;
} }
} }
@@ -202,7 +202,7 @@ namespace Content.Server.Hands.Components
/// <summary> /// <summary>
/// Checks if any hand can pick up an item. /// Checks if any hand can pick up an item.
/// </summary> /// </summary>
public bool CanPutInHand(ItemComponent item, bool mobCheck = true) public bool CanPutInHand(SharedItemComponent item, bool mobCheck = true)
{ {
var entity = item.Owner; var entity = item.Owner;

View File

@@ -3,8 +3,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Interaction; using Content.Server.Interaction;
using Content.Server.Inventory.Components; using Content.Server.Inventory;
using Content.Server.Items;
using Content.Server.Stack; using Content.Server.Stack;
using Content.Server.Storage.Components; using Content.Server.Storage.Components;
using Content.Server.Throwing; using Content.Server.Throwing;
@@ -13,6 +12,7 @@ using Content.Shared.Examine;
using Content.Shared.Hands; using Content.Shared.Hands;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Input; using Content.Shared.Input;
using Content.Shared.Inventory;
using Content.Shared.Physics.Pull; using Content.Shared.Physics.Pull;
using Content.Shared.Popups; using Content.Shared.Popups;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -26,14 +26,13 @@ using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Players; using Robust.Shared.Players;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Server.Hands.Systems namespace Content.Server.Hands.Systems
{ {
[UsedImplicitly] [UsedImplicitly]
internal sealed class HandsSystem : SharedHandsSystem internal sealed class HandsSystem : SharedHandsSystem
{ {
[Dependency] private readonly InteractionSystem _interactionSystem = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly StackSystem _stackSystem = default!; [Dependency] private readonly StackSystem _stackSystem = default!;
[Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!; [Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
@@ -261,15 +260,15 @@ namespace Content.Server.Hands.Systems
private void HandleSmartEquipBackpack(ICommonSession? session) private void HandleSmartEquipBackpack(ICommonSession? session)
{ {
HandleSmartEquip(session, Slots.BACKPACK); HandleSmartEquip(session, "back");
} }
private void HandleSmartEquipBelt(ICommonSession? session) private void HandleSmartEquipBelt(ICommonSession? session)
{ {
HandleSmartEquip(session, Slots.BELT); HandleSmartEquip(session, "belt");
} }
private void HandleSmartEquip(ICommonSession? session, Slots equipmentSlot) private void HandleSmartEquip(ICommonSession? session, string equipmentSlot)
{ {
if (session is not IPlayerSession playerSession) if (session is not IPlayerSession playerSession)
return; return;
@@ -277,14 +276,13 @@ namespace Content.Server.Hands.Systems
if (playerSession.AttachedEntity is not {Valid: true} plyEnt || !EntityManager.EntityExists(plyEnt)) if (playerSession.AttachedEntity is not {Valid: true} plyEnt || !EntityManager.EntityExists(plyEnt))
return; return;
if (!EntityManager.TryGetComponent(plyEnt, out SharedHandsComponent? hands) || if (!EntityManager.TryGetComponent(plyEnt, out SharedHandsComponent? hands))
!EntityManager.TryGetComponent(plyEnt, out InventoryComponent? inventory))
return; return;
if (!inventory.TryGetSlotItem(equipmentSlot, out ItemComponent? equipmentItem) || if (!_inventorySystem.TryGetSlotEntity(plyEnt, equipmentSlot, out var slotEntity) ||
!EntityManager.TryGetComponent(equipmentItem.Owner, out ServerStorageComponent? storageComponent)) !EntityManager.TryGetComponent(slotEntity, out ServerStorageComponent? storageComponent))
{ {
plyEnt.PopupMessage(Loc.GetString("hands-system-missing-equipment-slot", ("slotName", SlotNames[equipmentSlot].ToLower()))); plyEnt.PopupMessage(Loc.GetString("hands-system-missing-equipment-slot", ("slotName", equipmentSlot)));
return; return;
} }
@@ -296,7 +294,7 @@ namespace Content.Server.Hands.Systems
{ {
if (storageComponent.StoredEntities.Count == 0) if (storageComponent.StoredEntities.Count == 0)
{ {
plyEnt.PopupMessage(Loc.GetString("hands-system-empty-equipment-slot", ("slotName", SlotNames[equipmentSlot].ToLower()))); plyEnt.PopupMessage(Loc.GetString("hands-system-empty-equipment-slot", ("slotName", equipmentSlot)));
} }
else else
{ {

View File

@@ -5,16 +5,15 @@ using System.Threading.Tasks;
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.CombatMode; using Content.Server.CombatMode;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Pulling; using Content.Server.Pulling;
using Content.Server.Storage.Components; using Content.Server.Storage.Components;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
using Content.Shared.Administration.Logs;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.DragDrop; using Content.Shared.DragDrop;
using Content.Shared.Input; using Content.Shared.Input;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Interaction.Helpers; using Content.Shared.Interaction.Helpers;
using Content.Shared.Item;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Pulling.Components; using Content.Shared.Pulling.Components;
using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Melee;
@@ -358,7 +357,7 @@ namespace Content.Server.Interaction
} }
} }
} }
else if (!wideAttack && target != null && HasComp<ItemComponent>(target.Value)) else if (!wideAttack && target != null && HasComp<SharedItemComponent>(target.Value))
{ {
// We pick up items if our hand is empty, even if we're in combat mode. // We pick up items if our hand is empty, even if we're in combat mode.
InteractHand(user, target.Value); InteractHand(user, target.Value);

View File

@@ -1,40 +0,0 @@
using Content.Shared.Hands;
using Content.Shared.Inventory;
using Content.Shared.Popups;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.Inventory.Components
{
/// <summary>
/// Pops up a message when equipped / unequipped (including hands).
/// For debugging purposes.
/// </summary>
[RegisterComponent]
public class DebugEquipComponent : Component, IEquipped, IEquippedHand, IUnequipped, IUnequippedHand
{
[Dependency] private readonly IEntityManager _entMan = default!;
public override string Name => "DebugEquip";
void IEquipped.Equipped(EquippedEventArgs eventArgs)
{
eventArgs.User.PopupMessage("equipped " + _entMan.GetComponent<MetaDataComponent>(Owner).EntityName);
}
void IEquippedHand.EquippedHand(EquippedHandEventArgs eventArgs)
{
eventArgs.User.PopupMessage("equipped hand " + _entMan.GetComponent<MetaDataComponent>(Owner).EntityName);
}
void IUnequipped.Unequipped(UnequippedEventArgs eventArgs)
{
eventArgs.User.PopupMessage("unequipped " + _entMan.GetComponent<MetaDataComponent>(Owner).EntityName);
}
void IUnequippedHand.UnequippedHand(UnequippedHandEventArgs eventArgs)
{
eventArgs.User.PopupMessage("unequipped hand" + _entMan.GetComponent<MetaDataComponent>(Owner).EntityName);
}
}
}

View File

@@ -1,91 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Items;
using Content.Shared.Item;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Server.Inventory.Components
{
// Handles the special behavior of pockets/ID card slot and their relation to uniforms.
[RegisterComponent]
[ComponentReference(typeof(IInventoryController))]
public class HumanInventoryControllerComponent : Component, IInventoryController
{
public override string Name => "HumanInventoryController";
private InventoryComponent _inventory = default!;
protected override void Initialize()
{
base.Initialize();
_inventory = Owner.EnsureComponent<InventoryComponent>();
}
bool IInventoryController.CanEquip(Slots slot, EntityUid entity, bool flagsCheck, [NotNullWhen(false)] out string? reason)
{
var slotMask = SlotMasks[slot];
reason = null;
if ((slotMask & (SlotFlags.POCKET | SlotFlags.IDCARD)) != SlotFlags.NONE)
{
// Can't wear stuff in ID card or pockets unless you have a uniform.
if (_inventory.GetSlotItem(Slots.INNERCLOTHING) == null)
{
reason = Loc.GetString(slotMask == SlotFlags.IDCARD
? "human-inventory-controller-component-need-uniform-to-store-in-id-slot-text"
: "human-inventory-controller-component-need-uniform-to-store-in-pockets-text");
return false;
}
if (slotMask == SlotFlags.POCKET)
{
var itemComponent = IoCManager.Resolve<IEntityManager>().GetComponent<ItemComponent>(entity);
// If this item is small enough then it always fits in pockets.
if (itemComponent.Size <= (int) ReferenceSizes.Pocket)
{
return true;
}
else if (!flagsCheck)
{
reason = Loc.GetString("human-inventory-controller-component-too-large-text");
}
}
}
// Standard flag check.
return flagsCheck;
}
public void CheckUniformExists() { Owner.SpawnTimer(0, DropIdAndPocketsIfWeNoLongerHaveAUniform); }
// Hey, it's descriptive.
private void DropIdAndPocketsIfWeNoLongerHaveAUniform()
{
if (Deleted)
{
return;
}
if (_inventory.GetSlotItem(Slots.INNERCLOTHING) != null)
{
return;
}
void DropMaybe(Slots slot)
{
if (_inventory.GetSlotItem(slot) != null)
{
_inventory.Unequip(slot);
}
}
DropMaybe(Slots.POCKET1);
DropMaybe(Slots.POCKET2);
DropMaybe(Slots.IDCARD);
}
}
}

View File

@@ -1,28 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Robust.Shared.GameObjects;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Server.Inventory.Components
{
/// <summary>
/// Allows for overriding inventory-related behavior on an entity.
/// </summary>
public interface IInventoryController
{
/// <summary>
/// Can be implemented to override "can this item be equipped" behavior.
/// </summary>
/// <param name="slot">The slot to be equipped into.</param>
/// <param name="entity">The entity to equip.</param>
/// <param name="flagsCheck">Whether the entity passes default slot masks & flags checks.</param>
/// <param name="reason">The translated reason why the item cannot be equiped, if this function returns false. Can be null.</param>
/// <returns>True if the entity can be equipped, false otherwise</returns>
bool CanEquip(Slots slot, EntityUid entity, bool flagsCheck, [NotNullWhen(false)] out string? reason)
{
reason = null;
return flagsCheck;
}
bool CanEquip(Slots slot, EntityUid entity, bool flagsCheck) => CanEquip(slot, entity, flagsCheck, out _);
}
}

View File

@@ -1,576 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Clothing.Components;
using Content.Server.Hands.Components;
using Content.Server.Interaction;
using Content.Server.Items;
using Content.Server.Storage.Components;
using Content.Shared.ActionBlocker;
using Content.Shared.Acts;
using Content.Shared.Inventory;
using Content.Shared.Movement.EntitySystems;
using Content.Shared.Popups;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Players;
using Robust.Shared.ViewVariables;
using static Content.Shared.Inventory.EquipmentSlotDefines;
using static Content.Shared.Inventory.SharedInventoryComponent.ClientInventoryMessage;
namespace Content.Server.Inventory.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedInventoryComponent))]
public class InventoryComponent : SharedInventoryComponent, IExAct
{
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly IEntityManager _entities = default!;
[ViewVariables] private readonly Dictionary<Slots, ContainerSlot> _slotContainers = new();
private KeyValuePair<Slots, (EntityUid entity, bool fits)>? _hoverEntity;
public IEnumerable<Slots> Slots => _slotContainers.Keys;
public event Action? OnItemChanged;
protected override void Initialize()
{
base.Initialize();
foreach (var slotName in InventoryInstance.SlotMasks)
{
if (slotName != EquipmentSlotDefines.Slots.NONE)
{
AddSlot(slotName);
}
}
}
protected override void OnRemove()
{
var slots = _slotContainers.Keys.ToList();
foreach (var slot in slots)
{
if (TryGetSlotItem(slot, out ItemComponent? item))
{
_entities.DeleteEntity(item.Owner);
}
RemoveSlot(slot);
}
base.OnRemove();
}
public IEnumerable<EntityUid> GetAllHeldItems()
{
foreach (var (_, container) in _slotContainers)
{
foreach (var entity in container.ContainedEntities)
{
yield return entity;
}
}
}
/// <summary>
/// Helper to get container name for specified slot on this component
/// </summary>
/// <param name="slot"></param>
/// <returns></returns>
private string GetSlotString(Slots slot)
{
return Name + "_" + Enum.GetName(typeof(Slots), slot);
}
/// <summary>
/// Gets the clothing equipped to the specified slot.
/// </summary>
/// <param name="slot">The slot to get the item for.</param>
/// <returns>Null if the slot is empty, otherwise the item.</returns>
public ItemComponent? GetSlotItem(Slots slot)
{
return GetSlotItem<ItemComponent>(slot);
}
public IEnumerable<T?> LookupItems<T>() where T : Component
{
return _slotContainers.Values
.SelectMany(x => x.ContainedEntities.Select(e => _entities.GetComponentOrNull<T>(e)))
.Where(x => x != null);
}
public T? GetSlotItem<T>(Slots slot) where T : ItemComponent
{
if (!_slotContainers.ContainsKey(slot))
{
return null;
}
var containedEntity = _slotContainers[slot].ContainedEntity;
if (containedEntity != null && _entities.GetComponent<MetaDataComponent>(containedEntity.Value).EntityDeleted)
{
_slotContainers.Remove(slot);
containedEntity = null;
Dirty();
}
return containedEntity.HasValue ? _entities.GetComponent<T>(containedEntity.Value) : null;
}
public bool TryGetSlotItem<T>(Slots slot, [NotNullWhen(true)] out T? itemComponent) where T : ItemComponent
{
itemComponent = GetSlotItem<T>(slot);
return itemComponent != null;
}
/// <summary>
/// Equips slothing to the specified slot.
/// </summary>
/// <remarks>
/// This will fail if there is already an item in the specified slot.
/// </remarks>
/// <param name="slot">The slot to put the item in.</param>
/// <param name="item">The item to insert into the slot.</param>
/// <param name="mobCheck">Whether to perform an ActionBlocker check to the entity.</param>
/// <param name="reason">The translated reason why the item cannot be equipped, if this function returns false. Can be null.</param>
/// <returns>True if the item was successfully inserted, false otherwise.</returns>
public bool Equip(Slots slot, ItemComponent item, bool mobCheck, [NotNullWhen(false)] out string? reason)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item),
"Clothing must be passed here. To remove some clothing from a slot, use Unequip()");
}
if (!CanEquip(slot, item, mobCheck, out reason))
{
return false;
}
var inventorySlot = _slotContainers[slot];
if (!inventorySlot.Insert(item.Owner))
{
reason = Loc.GetString("inventory-component-on-equip-cannot");
return false;
}
// TODO: Make clothing component not inherit ItemComponent, for fuck's sake.
// TODO: Make clothing component not required for playing a sound on equip... Move it to its own component.
if (mobCheck && item is ClothingComponent { EquipSound: {} equipSound })
{
SoundSystem.Play(Filter.Pvs(Owner), equipSound.GetSound(), Owner, AudioParams.Default.WithVolume(-2f));
}
_entitySystemManager.GetEntitySystem<InteractionSystem>().EquippedInteraction(Owner, item.Owner, slot);
OnItemChanged?.Invoke();
Dirty();
UpdateMovementSpeed();
return true;
}
public bool Equip(Slots slot, ItemComponent item, bool mobCheck = true) =>
Equip(slot, item, mobCheck, out var _);
public bool Equip(Slots slot, EntityUid entity, bool mobCheck = true) =>
Equip(slot, _entities.GetComponent<ItemComponent>(entity), mobCheck);
/// <summary>
/// Checks whether an item can be put in the specified slot.
/// </summary>
/// <param name="slot">The slot to check for.</param>
/// <param name="item">The item to check for.</param>
/// <param name="reason">The translated reason why the item cannot be equiped, if this function returns false. Can be null.</param>
/// <returns>True if the item can be inserted into the specified slot.</returns>
public bool CanEquip(Slots slot, ItemComponent item, bool mobCheck, [NotNullWhen(false)] out string? reason)
{
var pass = false;
reason = null;
if (mobCheck && !EntitySystem.Get<ActionBlockerSystem>().CanEquip(Owner))
{
reason = Loc.GetString("inventory-component-can-equip-cannot");
return false;
}
if (item is ClothingComponent clothing)
{
if (clothing.SlotFlags != SlotFlags.PREVENTEQUIP && (clothing.SlotFlags & SlotMasks[slot]) != 0)
{
pass = true;
}
else
{
reason = Loc.GetString("inventory-component-can-equip-does-not-fit");
}
}
if (_entities.TryGetComponent(Owner, out IInventoryController? controller))
{
pass = controller.CanEquip(slot, item.Owner, pass, out var controllerReason);
reason = controllerReason ?? reason;
}
if (!pass)
{
reason = reason ?? Loc.GetString("inventory-component-can-equip-cannot");
return false;
}
var canEquip = pass && _slotContainers[slot].CanInsert(item.Owner);
if (!canEquip)
{
reason = Loc.GetString("inventory-component-can-equip-cannot");
}
return canEquip;
}
public bool CanEquip(Slots slot, ItemComponent item, bool mobCheck = true) =>
CanEquip(slot, item, mobCheck, out var _);
public bool CanEquip(Slots slot, EntityUid entity, bool mobCheck = true) =>
CanEquip(slot, _entities.GetComponent<ItemComponent>(entity), mobCheck);
/// <summary>
/// Drops the item in a slot.
/// </summary>
/// <param name="slot">The slot to drop the item from.</param>
/// <returns>True if an item was dropped, false otherwise.</returns>
/// <param name="mobCheck">Whether to perform an ActionBlocker check to the entity.</param>
public bool Unequip(Slots slot, bool mobCheck = true)
{
if (!CanUnequip(slot, mobCheck))
{
return false;
}
var inventorySlot = _slotContainers[slot];
if (inventorySlot.ContainedEntity is not {Valid: true} entity)
{
return false;
}
if (!inventorySlot.Remove(entity))
{
return false;
}
// TODO: The item should be dropped to the container our owner is in, if any.
_entities.GetComponent<TransformComponent>(entity).AttachParentToContainerOrGrid();
_entitySystemManager.GetEntitySystem<InteractionSystem>().UnequippedInteraction(Owner, entity, slot);
OnItemChanged?.Invoke();
Dirty();
UpdateMovementSpeed();
return true;
}
private void UpdateMovementSpeed()
{
EntitySystem.Get<MovementSpeedModifierSystem>().RefreshMovementSpeedModifiers(Owner);
}
public void ForceUnequip(Slots slot)
{
var inventorySlot = _slotContainers[slot];
if (inventorySlot.ContainedEntity is not {Valid: true} entity)
{
return;
}
var item = _entities.GetComponent<ItemComponent>(entity);
inventorySlot.ForceRemove(entity);
var itemTransform = _entities.GetComponent<TransformComponent>(entity);
itemTransform.AttachParentToContainerOrGrid();
_entitySystemManager.GetEntitySystem<InteractionSystem>().UnequippedInteraction(Owner, item.Owner, slot);
OnItemChanged?.Invoke();
Dirty();
}
/// <summary>
/// Checks whether an item can be dropped from the specified slot.
/// </summary>
/// <param name="slot">The slot to check for.</param>
/// <param name="mobCheck">Whether to perform an ActionBlocker check to the entity.</param>
/// <returns>
/// True if there is an item in the slot and it can be dropped, false otherwise.
/// </returns>
public bool CanUnequip(Slots slot, bool mobCheck = true)
{
if (mobCheck && !EntitySystem.Get<ActionBlockerSystem>().CanUnequip(Owner))
return false;
var inventorySlot = _slotContainers[slot];
return inventorySlot.ContainedEntity != null && inventorySlot.CanRemove(inventorySlot.ContainedEntity.Value);
}
/// <summary>
/// Adds a new slot to this inventory component.
/// </summary>
/// <param name="slot">The name of the slot to add.</param>
/// <exception cref="InvalidOperationException">
/// Thrown if the slot with specified name already exists.
/// </exception>
public ContainerSlot AddSlot(Slots slot)
{
if (HasSlot(slot))
{
throw new InvalidOperationException($"Slot '{slot}' already exists.");
}
Dirty();
var container = ContainerHelpers.CreateContainer<ContainerSlot>(Owner, GetSlotString(slot));
container.OccludesLight = false;
_slotContainers[slot] = container;
OnItemChanged?.Invoke();
return _slotContainers[slot];
}
/// <summary>
/// Removes a slot from this inventory component.
/// </summary>
/// <remarks>
/// If the slot contains an item, the item is dropped.
/// </remarks>
/// <param name="slot">The name of the slot to remove.</param>
public void RemoveSlot(Slots slot)
{
if (!HasSlot(slot))
{
throw new InvalidOperationException($"Slot '{slot}' does not exist.");
}
ForceUnequip(slot);
var container = _slotContainers[slot];
container.Shutdown();
_slotContainers.Remove(slot);
OnItemChanged?.Invoke();
Dirty();
}
/// <summary>
/// Checks whether a slot with the specified name exists.
/// </summary>
/// <param name="slot">The slot name to check.</param>
/// <returns>True if the slot exists, false otherwise.</returns>
public bool HasSlot(Slots slot)
{
return _slotContainers.ContainsKey(slot);
}
/// <summary>
/// The underlying Container System just notified us that an entity was removed from it.
/// We need to make sure we process that removed entity as being unequipped from the slot.
/// </summary>
public void ForceUnequip(IContainer container, EntityUid entity)
{
// make sure this is one of our containers.
// Technically the correct way would be to enumerate the possible slot names
// comparing with this container, but I might as well put the dictionary to good use.
if (container is not ContainerSlot slot || !_slotContainers.ContainsValue(slot))
return;
if (_entities.TryGetComponent(entity, out ItemComponent? itemComp))
{
itemComp.RemovedFromSlot();
}
OnItemChanged?.Invoke();
Dirty();
}
/// <summary>
/// Message that tells us to equip or unequip items from the inventory slots
/// </summary>
/// <param name="msg"></param>
private async void HandleInventoryMessage(ClientInventoryMessage msg)
{
switch (msg.Updatetype)
{
case ClientInventoryUpdate.Equip:
{
var hands = _entities.GetComponent<HandsComponent>(Owner);
var activeHand = hands.ActiveHand;
var activeItem = hands.GetActiveHand;
if (activeHand != null && activeItem != null && _entities.TryGetComponent(activeItem.Owner, out ItemComponent? item))
{
hands.TryDropNoInteraction();
if (!Equip(msg.Inventoryslot, item, true, out var reason))
{
hands.PutInHand(item);
Owner.PopupMessageCursor(reason);
}
}
break;
}
case ClientInventoryUpdate.Use:
{
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
var hands = _entities.GetComponent<HandsComponent>(Owner);
var activeHand = hands.GetActiveHand;
var itemContainedInSlot = GetSlotItem(msg.Inventoryslot);
if (itemContainedInSlot != null)
{
if (activeHand != null)
{
await interactionSystem.InteractUsing(Owner, activeHand.Owner, itemContainedInSlot.Owner,
new EntityCoordinates());
}
else if (Unequip(msg.Inventoryslot))
{
hands.PutInHand(itemContainedInSlot);
}
}
break;
}
case ClientInventoryUpdate.Hover:
{
var hands = _entities.GetComponent<HandsComponent>(Owner);
var activeHand = hands.GetActiveHand;
if (activeHand != null && GetSlotItem(msg.Inventoryslot) == null)
{
var canEquip = CanEquip(msg.Inventoryslot, activeHand, true, out var reason);
_hoverEntity =
new KeyValuePair<Slots, (EntityUid entity, bool fits)>(msg.Inventoryslot,
(Uid: activeHand.Owner, canEquip));
Dirty();
}
break;
}
}
}
/// <inheritdoc />
[Obsolete("Component Messages are deprecated, use Entity Events instead.")]
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel,
ICommonSession? session = null)
{
base.HandleNetworkMessage(message, netChannel, session);
if (session == null)
{
throw new ArgumentNullException(nameof(session));
}
switch (message)
{
case ClientInventoryMessage msg:
var playerentity = session.AttachedEntity;
if (playerentity == Owner)
HandleInventoryMessage(msg);
break;
case OpenSlotStorageUIMessage msg:
if (!HasSlot(msg.Slot)) // client input sanitization
return;
var item = GetSlotItem(msg.Slot);
if (item != null && _entities.TryGetComponent(item.Owner, out ServerStorageComponent? storage))
storage.OpenStorageUI(Owner);
break;
}
}
public override ComponentState GetComponentState()
{
var list = new List<KeyValuePair<Slots, EntityUid>>();
foreach (var (slot, container) in _slotContainers)
{
if (container is {ContainedEntity: { }})
{
list.Add(new KeyValuePair<Slots, EntityUid>(slot, container.ContainedEntity.Value));
}
}
var hover = _hoverEntity;
_hoverEntity = null;
return new InventoryComponentState(list, hover);
}
void IExAct.OnExplosion(ExplosionEventArgs eventArgs)
{
if (eventArgs.Severity < ExplosionSeverity.Heavy)
{
return;
}
foreach (var slot in _slotContainers.Values.ToList())
{
foreach (var entity in slot.ContainedEntities)
{
var exActs = _entities.GetComponents<IExAct>(entity).ToList();
foreach (var exAct in exActs)
{
exAct.OnExplosion(eventArgs);
}
}
}
}
public override bool IsEquipped(EntityUid item)
{
if (item == default) return false;
foreach (var containerSlot in _slotContainers.Values)
{
// we don't want a recursive check here
if (containerSlot.Contains(item))
{
return true;
}
}
return false;
}
public override bool TryGetSlot(Slots slot, [NotNullWhen(true)] out EntityUid? item)
{
if (_slotContainers.TryGetValue(slot, out var container))
{
item = container.ContainedEntity;
return item != null;
}
item = null;
return false;
}
}
}

View File

@@ -1,48 +0,0 @@
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Server.Inventory
{
public static class InventoryHelpers
{
public static bool SpawnItemInSlot(this InventoryComponent inventory, Slots slot, string prototype, bool mobCheck = false)
{
var entityManager = IoCManager.Resolve<IEntityManager>();
var protoManager = IoCManager.Resolve<IPrototypeManager>();
var user = inventory.Owner;
// Let's do nothing if the owner of the inventory has been deleted.
if (entityManager.Deleted(user))
return false;
// If we don't have that slot or there's already an item there, we do nothing.
if (!inventory.HasSlot(slot) || inventory.TryGetSlotItem(slot, out ItemComponent? _))
return false;
// If the prototype in question doesn't exist, we do nothing.
if (!protoManager.HasIndex<EntityPrototype>(prototype))
return false;
// Let's spawn this first...
var item = entityManager.SpawnEntity(prototype, entityManager.GetComponent<TransformComponent>(user).MapPosition);
// Helper method that deletes the item and returns false.
bool DeleteItem()
{
entityManager.DeleteEntity(item);
return false;
}
// If this doesn't have an item component, then we can't do anything with it.
if (!entityManager.TryGetComponent(item, out ItemComponent? itemComp))
return DeleteItem();
// We finally try to equip the item, otherwise we delete it.
return inventory.Equip(slot, itemComp, mobCheck) || DeleteItem();
}
}
}

View File

@@ -1,88 +0,0 @@
using Content.Server.Atmos;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.Temperature.Systems;
using Content.Shared.Inventory;
using Content.Shared.Slippery;
using Content.Shared.Damage;
using Content.Shared.Electrocution;
using Content.Shared.Movement.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
namespace Content.Server.Inventory
{
class InventorySystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HumanInventoryControllerComponent, EntRemovedFromContainerMessage>(HandleRemovedFromContainer);
SubscribeLocalEvent<InventoryComponent, EntRemovedFromContainerMessage>(HandleInvRemovedFromContainer);
SubscribeLocalEvent<InventoryComponent, HighPressureEvent>(OnHighPressureEvent);
SubscribeLocalEvent<InventoryComponent, LowPressureEvent>(OnLowPressureEvent);
SubscribeLocalEvent<InventoryComponent, DamageModifyEvent>(OnDamageModify);
SubscribeLocalEvent<InventoryComponent, ElectrocutionAttemptEvent>(OnElectrocutionAttempt);
SubscribeLocalEvent<InventoryComponent, SlipAttemptEvent>(OnSlipAttemptEvent);
SubscribeLocalEvent<InventoryComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
SubscribeLocalEvent<InventoryComponent, ModifyChangedTemperatureEvent>(OnModifyTemperature);
}
private void OnModifyTemperature(EntityUid uid, InventoryComponent component, ModifyChangedTemperatureEvent args)
{
RelayInventoryEvent(component, args);
}
private void OnSlipAttemptEvent(EntityUid uid, InventoryComponent component, SlipAttemptEvent args)
{
if (component.TryGetSlotItem(EquipmentSlotDefines.Slots.SHOES, out ItemComponent? shoes))
{
RaiseLocalEvent(shoes.Owner, args, false);
}
}
private void OnRefreshMovespeed(EntityUid uid, InventoryComponent component, RefreshMovementSpeedModifiersEvent args)
{
RelayInventoryEvent(component, args);
}
private static void HandleInvRemovedFromContainer(EntityUid uid, InventoryComponent component, EntRemovedFromContainerMessage args)
{
component.ForceUnequip(args.Container, args.Entity);
}
private static void HandleRemovedFromContainer(EntityUid uid, HumanInventoryControllerComponent component, EntRemovedFromContainerMessage args)
{
component.CheckUniformExists();
}
private void OnHighPressureEvent(EntityUid uid, InventoryComponent component, HighPressureEvent args)
{
RelayInventoryEvent(component, args);
}
private void OnLowPressureEvent(EntityUid uid, InventoryComponent component, LowPressureEvent args)
{
RelayInventoryEvent(component, args);
}
private void OnElectrocutionAttempt(EntityUid uid, InventoryComponent component, ElectrocutionAttemptEvent args)
{
RelayInventoryEvent(component, args);
}
private void OnDamageModify(EntityUid uid, InventoryComponent component, DamageModifyEvent args)
{
RelayInventoryEvent(component, args);
}
private void RelayInventoryEvent<T>(InventoryComponent component, T args) where T : EntityEventArgs
{
foreach (var equipped in component.GetAllHeldItems())
{
RaiseLocalEvent(equipped, args, false);
}
}
}
}

View File

@@ -0,0 +1,8 @@
using Content.Shared.Inventory;
using Robust.Shared.GameObjects;
namespace Content.Server.Inventory;
[RegisterComponent]
[ComponentReference(typeof(InventoryComponent))]
public class ServerInventoryComponent : InventoryComponent { }

View File

@@ -0,0 +1,70 @@
using Content.Server.Atmos;
using Content.Server.Hands.Components;
using Content.Server.Interaction;
using Content.Server.Storage.Components;
using Content.Server.Temperature.Systems;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using InventoryComponent = Content.Shared.Inventory.InventoryComponent;
namespace Content.Server.Inventory
{
class ServerInventorySystem : InventorySystem
{
[Dependency] private readonly InteractionSystem _interactionSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<InventoryComponent, HighPressureEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, LowPressureEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, ModifyChangedTemperatureEvent>(RelayInventoryEvent);
SubscribeNetworkEvent<TryEquipNetworkMessage>(OnNetworkEquip);
SubscribeNetworkEvent<TryUnequipNetworkMessage>(OnNetworkUnequip);
SubscribeNetworkEvent<OpenSlotStorageNetworkMessage>(OnOpenSlotStorage);
SubscribeNetworkEvent<UseSlotNetworkMessage>(OnUseSlot);
}
private void OnUseSlot(UseSlotNetworkMessage ev)
{
if (!TryComp<HandsComponent>(ev.Uid, out var hands) || !TryGetSlotEntity(ev.Uid, ev.Slot, out var itemUid))
return;
var activeHand = hands.GetActiveHand;
if (activeHand != null)
{
_interactionSystem.InteractUsing(ev.Uid, activeHand.Owner, itemUid.Value,
new EntityCoordinates());
}
else if (TryUnequip(ev.Uid, ev.Slot))
{
hands.PutInHand(itemUid.Value);
}
}
private void OnOpenSlotStorage(OpenSlotStorageNetworkMessage ev)
{
if (TryGetSlotEntity(ev.Uid, ev.Slot, out var entityUid) && TryComp<ServerStorageComponent>(entityUid, out var storageComponent))
{
storageComponent.OpenStorageUI(ev.Uid);
}
}
private void OnNetworkUnequip(TryUnequipNetworkMessage ev)
{
TryUnequip(ev.Actor, ev.Target, ev.Slot, ev.Silent, ev.Force);
}
private void OnNetworkEquip(TryEquipNetworkMessage ev)
{
TryEquip(ev.Actor, ev.Target, ev.ItemUid, ev.Slot, ev.Silent, ev.Force);
}
}
}

View File

@@ -1,30 +0,0 @@
using System.Collections.Generic;
using Content.Shared.Item;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.Items
{
[RegisterComponent]
[ComponentReference(typeof(SharedItemComponent))]
public class ItemComponent : SharedItemComponent
{
public override void RemovedFromSlot()
{
foreach (var component in IoCManager.Resolve<IEntityManager>().GetComponents<ISpriteRenderableComponent>(Owner))
{
component.Visible = true;
}
}
public override void EquippedToSlot()
{
foreach (var component in IoCManager.Resolve<IEntityManager>().GetComponents<ISpriteRenderableComponent>(Owner))
{
component.Visible = false;
}
}
}
}

View File

@@ -1,6 +1,6 @@
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Holiday; using Content.Server.Holiday;
using Content.Server.Items; using Content.Shared.Item;
using Content.Shared.Roles; using Content.Shared.Roles;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -33,7 +33,7 @@ namespace Content.Server.Jobs
var entity = entMan.SpawnEntity(Prototype, entMan.GetComponent<TransformComponent>(mob).Coordinates); var entity = entMan.SpawnEntity(Prototype, entMan.GetComponent<TransformComponent>(mob).Coordinates);
if (!entMan.TryGetComponent(entity, out ItemComponent? item) || !entMan.TryGetComponent(mob, out HandsComponent? hands)) if (!entMan.TryGetComponent(entity, out SharedItemComponent? item) || !entMan.TryGetComponent(mob, out HandsComponent? hands))
return; return;
hands.PutInHand(item, false); hands.PutInHand(item, false);

View File

@@ -6,7 +6,6 @@ using Content.Server.Chat.Managers;
using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.UserInterface; using Content.Server.UserInterface;
@@ -16,6 +15,7 @@ using Content.Shared.Body.Part;
using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Kitchen; using Content.Shared.Kitchen;
using Content.Shared.Kitchen.Components; using Content.Shared.Kitchen.Components;
using Content.Shared.Popups; using Content.Shared.Popups;
@@ -284,7 +284,7 @@ namespace Content.Server.Kitchen.Components
return true; return true;
} }
if (!_entities.TryGetComponent(itemEntity, typeof(ItemComponent), out var food)) if (!_entities.TryGetComponent(itemEntity, typeof(SharedItemComponent), out var food))
{ {
Owner.PopupMessage(eventArgs.User, "microwave-component-interact-using-transfer-fail"); Owner.PopupMessage(eventArgs.User, "microwave-component-interact-using-transfer-fail");
return false; return false;

View File

@@ -2,13 +2,13 @@
using System.Linq; using System.Linq;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Kitchen.Components; using Content.Server.Kitchen.Components;
using Content.Server.Kitchen.Events; using Content.Server.Kitchen.Events;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Stack; using Content.Server.Stack;
using Content.Server.UserInterface; using Content.Server.UserInterface;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Kitchen.Components; using Content.Shared.Kitchen.Components;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Random.Helpers; using Content.Shared.Random.Helpers;
@@ -264,7 +264,7 @@ namespace Content.Server.Kitchen.EntitySystems
if (user == null || if (user == null ||
!EntityManager.TryGetComponent<HandsComponent?>(user.Value, out var hands) || !EntityManager.TryGetComponent<HandsComponent?>(user.Value, out var hands) ||
!EntityManager.TryGetComponent<ItemComponent?>(beaker, out var item)) !EntityManager.TryGetComponent<SharedItemComponent?>(beaker, out var item))
return; return;
hands.PutInHandOrDrop(item); hands.PutInHandOrDrop(item);

View File

@@ -1,5 +1,3 @@
using System;
using Content.Server.Items;
using Content.Shared.Whitelist; using Content.Shared.Whitelist;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;

View File

@@ -1,6 +1,6 @@
using Content.Server.Clothing.Components; using Content.Server.Clothing.Components;
using Content.Server.Items;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Light.Component; using Content.Shared.Light.Component;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
@@ -38,7 +38,7 @@ namespace Content.Server.Light.Components
{ {
base.Initialize(); base.Initialize();
if (_entMan.TryGetComponent<ItemComponent?>(Owner, out var item)) if (_entMan.TryGetComponent<SharedItemComponent?>(Owner, out var item))
{ {
item.EquippedPrefix = "unlit"; item.EquippedPrefix = "unlit";
} }
@@ -55,7 +55,7 @@ namespace Content.Server.Light.Components
{ {
if (!Activated && CurrentState == ExpendableLightState.BrandNew) if (!Activated && CurrentState == ExpendableLightState.BrandNew)
{ {
if (_entMan.TryGetComponent<ItemComponent?>(Owner, out var item)) if (_entMan.TryGetComponent<SharedItemComponent?>(Owner, out var item))
{ {
item.EquippedPrefix = "lit"; item.EquippedPrefix = "lit";
} }
@@ -130,7 +130,7 @@ namespace Content.Server.Light.Components
if (_entMan.TryGetComponent(Owner, out ClothingComponent? clothing)) if (_entMan.TryGetComponent(Owner, out ClothingComponent? clothing))
{ {
clothing.ClothingEquippedPrefix = on ? "Activated" : string.Empty; clothing.EquippedPrefix = on ? "Activated" : string.Empty;
} }
} }
@@ -163,7 +163,7 @@ namespace Content.Server.Light.Components
UpdateSpriteAndSounds(Activated); UpdateSpriteAndSounds(Activated);
UpdateVisualizer(); UpdateVisualizer();
if (_entMan.TryGetComponent<ItemComponent?>(Owner, out var item)) if (_entMan.TryGetComponent<SharedItemComponent?>(Owner, out var item))
{ {
item.EquippedPrefix = "unlit"; item.EquippedPrefix = "unlit";
} }

View File

@@ -1,13 +1,27 @@
using System.Threading.Tasks;
using Content.Server.Clothing.Components;
using Content.Server.Light.EntitySystems; using Content.Server.Light.EntitySystems;
using Content.Server.PowerCell.Components; using Content.Server.PowerCell.Components;
using Content.Shared.ActionBlocker;
using Content.Shared.Actions;
using Content.Shared.Actions.Behaviors.Item; using Content.Shared.Actions.Behaviors.Item;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Light.Component; using Content.Shared.Light.Component;
using Content.Shared.Popups;
using Content.Shared.Rounding;
using Content.Shared.Sound; using Content.Shared.Sound;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Shared.Analyzers; using Robust.Shared.Analyzers;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Player;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
namespace Content.Server.Light.Components namespace Content.Server.Light.Components

View File

@@ -1,7 +1,5 @@
using Content.Shared.Smoking; using Content.Shared.Smoking;
using Content.Shared.Sound; using Content.Shared.Sound;
using Content.Shared.Temperature;
using Content.Server.Items;
using Content.Server.Light.EntitySystems; using Content.Server.Light.EntitySystems;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Analyzers; using Robust.Shared.Analyzers;

View File

@@ -1,7 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Content.Server.Clothing.Components; using Content.Server.Clothing.Components;
using Content.Server.Items;
using Content.Server.Light.Components; using Content.Server.Light.Components;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Server.PowerCell.Components; using Content.Server.PowerCell.Components;
@@ -228,11 +226,6 @@ namespace Content.Server.Light.EntitySystems
light.Enabled = on; light.Enabled = on;
} }
if (EntityManager.TryGetComponent(component.Owner, out ClothingComponent? clothing))
{
clothing.ClothingEquippedPrefix = Loc.GetString(on ? "on" : "off");
}
if (EntityManager.TryGetComponent(component.Owner, out ItemComponent? item)) if (EntityManager.TryGetComponent(component.Owner, out ItemComponent? item))
{ {
item.EquippedPrefix = Loc.GetString(on ? "on" : "off"); item.EquippedPrefix = Loc.GetString(on ? "on" : "off");

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.EntitySystems;
using Content.Server.Items;
using Content.Server.Light.Components; using Content.Server.Light.Components;
using Content.Shared.Audio; using Content.Shared.Audio;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Smoking; using Content.Shared.Smoking;
using Content.Shared.Temperature; using Content.Shared.Temperature;
using Robust.Shared.Audio; using Robust.Shared.Audio;
@@ -90,7 +90,7 @@ namespace Content.Server.Light.EntitySystems
component.PointLightComponent.Enabled = component.CurrentState == SmokableState.Lit; component.PointLightComponent.Enabled = component.CurrentState == SmokableState.Lit;
} }
if (EntityManager.TryGetComponent(component.Owner, out ItemComponent? item)) if (EntityManager.TryGetComponent(component.Owner, out SharedItemComponent? item))
{ {
switch (component.CurrentState) switch (component.CurrentState)
{ {

View File

@@ -38,7 +38,7 @@ namespace Content.Server.Medical.SuitSensors
/// Activate sensor if user wear it in this slot. /// Activate sensor if user wear it in this slot.
/// </summary> /// </summary>
[DataField("activationSlot")] [DataField("activationSlot")]
public EquipmentSlotDefines.Slots ActivationSlot = EquipmentSlotDefines.Slots.INNERCLOTHING; public string ActivationSlot = "jumpsuit";
/// <summary> /// <summary>
/// How often does sensor update its owners status (in seconds). /// How often does sensor update its owners status (in seconds).

View File

@@ -8,6 +8,7 @@ using Content.Shared.ActionBlocker;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Content.Shared.Medical.SuitSensor; using Content.Shared.Medical.SuitSensor;
using Content.Shared.MobState.Components; using Content.Shared.MobState.Components;
using Content.Shared.Verbs; using Content.Shared.Verbs;
@@ -37,8 +38,8 @@ namespace Content.Server.Medical.SuitSensors
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<SuitSensorComponent, MapInitEvent>(OnMapInit); SubscribeLocalEvent<SuitSensorComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<SuitSensorComponent, EquippedEvent>(OnEquipped); SubscribeLocalEvent<SuitSensorComponent, GotEquippedEvent>(OnEquipped);
SubscribeLocalEvent<SuitSensorComponent, UnequippedEvent>(OnUnequipped); SubscribeLocalEvent<SuitSensorComponent, GotUnequippedEvent>(OnUnequipped);
SubscribeLocalEvent<SuitSensorComponent, ExaminedEvent>(OnExamine); SubscribeLocalEvent<SuitSensorComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<SuitSensorComponent, GetInteractionVerbsEvent>(OnVerb); SubscribeLocalEvent<SuitSensorComponent, GetInteractionVerbsEvent>(OnVerb);
} }
@@ -91,15 +92,15 @@ namespace Content.Server.Medical.SuitSensors
} }
} }
private void OnEquipped(EntityUid uid, SuitSensorComponent component, EquippedEvent args) private void OnEquipped(EntityUid uid, SuitSensorComponent component, GotEquippedEvent args)
{ {
if (args.Slot != component.ActivationSlot) if (args.Slot != component.ActivationSlot)
return; return;
component.User = args.User; component.User = args.Equipee;
} }
private void OnUnequipped(EntityUid uid, SuitSensorComponent component, UnequippedEvent args) private void OnUnequipped(EntityUid uid, SuitSensorComponent component, GotUnequippedEvent args)
{ {
if (args.Slot != component.ActivationSlot) if (args.Slot != component.ActivationSlot)
return; return;
@@ -216,7 +217,7 @@ namespace Content.Server.Medical.SuitSensors
// try to get mobs id from ID slot // try to get mobs id from ID slot
var userName = Loc.GetString("suit-sensor-component-unknown-name"); var userName = Loc.GetString("suit-sensor-component-unknown-name");
var userJob = Loc.GetString("suit-sensor-component-unknown-job"); var userJob = Loc.GetString("suit-sensor-component-unknown-job");
if (_idCardSystem.TryGetIdCardSlot(sensor.User.Value, out var card)) if (_idCardSystem.TryFindIdCard(sensor.User.Value, out var card))
{ {
if (card.FullName != null) if (card.FullName != null)
userName = card.FullName; userName = card.FullName;

View File

@@ -1,12 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Content.Server.Body.Components; using Content.Server.Body.Components;
using Content.Server.Body.Systems; using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.DoAfter; using Content.Server.DoAfter;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.Nutrition.Components; using Content.Server.Nutrition.Components;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
@@ -17,20 +14,17 @@ using Content.Shared.Database;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Interaction.Helpers; using Content.Shared.Interaction.Helpers;
using Content.Shared.Inventory;
using Content.Shared.MobState.Components; using Content.Shared.MobState.Components;
using Content.Shared.Tag;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Player; using Robust.Shared.Player;
using System.Collections.Generic;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Content.Server.Inventory.Components;
using Content.Shared.Inventory;
using Content.Shared.Hands; using Content.Shared.Hands;
using Content.Shared.Inventory;
using Content.Shared.Item;
namespace Content.Server.Nutrition.EntitySystems namespace Content.Server.Nutrition.EntitySystems
{ {
@@ -47,6 +41,7 @@ namespace Content.Server.Nutrition.EntitySystems
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!; [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SharedAdminLogSystem _logSystem = default!; [Dependency] private readonly SharedAdminLogSystem _logSystem = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -228,7 +223,7 @@ namespace Content.Server.Nutrition.EntitySystems
EntityManager.DeleteEntity((component).Owner); EntityManager.DeleteEntity((component).Owner);
// Put the trash in the user's hand // Put the trash in the user's hand
if (EntityManager.TryGetComponent(finisher, out ItemComponent? item) && if (EntityManager.TryGetComponent(finisher, out SharedItemComponent? item) &&
handsComponent.CanPutInHand(item)) handsComponent.CanPutInHand(item))
{ {
handsComponent.PutInHand(item); handsComponent.PutInHand(item);
@@ -485,20 +480,20 @@ namespace Content.Server.Nutrition.EntitySystems
IngestionBlockerComponent blocker; IngestionBlockerComponent blocker;
if (component.TryGetSlotItem(EquipmentSlotDefines.Slots.MASK, out ItemComponent? mask) && if (_inventorySystem.TryGetSlotEntity(uid, "mask", out var maskUid) &&
EntityManager.TryGetComponent(mask.Owner, out blocker) && EntityManager.TryGetComponent(maskUid, out blocker) &&
blocker.Enabled) blocker.Enabled)
{ {
args.Blocker = mask.Owner; args.Blocker = maskUid;
args.Cancel(); args.Cancel();
return; return;
} }
if (component.TryGetSlotItem(EquipmentSlotDefines.Slots.HEAD, out ItemComponent? head) && if (_inventorySystem.TryGetSlotEntity(uid, "head", out var headUid) &&
EntityManager.TryGetComponent(head.Owner, out blocker) && EntityManager.TryGetComponent(headUid, out blocker) &&
blocker.Enabled) blocker.Enabled)
{ {
args.Blocker = head.Owner; args.Blocker = headUid;
args.Cancel(); args.Cancel();
} }
} }

View File

@@ -1,12 +1,12 @@
using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Nutrition.Components; using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -69,7 +69,7 @@ namespace Content.Server.Nutrition.EntitySystems
{ {
if (ContainerHelpers.IsInContainer(component.Owner)) if (ContainerHelpers.IsInContainer(component.Owner))
{ {
handsComponent.PutInHandOrDrop(EntityManager.GetComponent<ItemComponent>(sliceUid)); handsComponent.PutInHandOrDrop(EntityManager.GetComponent<SharedItemComponent>(sliceUid));
} }
} }

View File

@@ -1,7 +1,7 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Inventory;
using Content.Shared.PDA; using Content.Shared.PDA;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -18,7 +18,7 @@ namespace Content.Server.PDA
/// <returns>The id card component.</returns> /// <returns>The id card component.</returns>
public static IdCardComponent? GetHeldId(this EntityUid player) public static IdCardComponent? GetHeldId(this EntityUid player)
{ {
IdCardComponent? firstIdInPda = null; IdCardComponent? foundPDAId = null;
var entMan = IoCManager.Resolve<IEntityManager>(); var entMan = IoCManager.Resolve<IEntityManager>();
@@ -26,11 +26,10 @@ namespace Content.Server.PDA
{ {
foreach (var item in hands.GetAllHeldItems()) foreach (var item in hands.GetAllHeldItems())
{ {
if (firstIdInPda == null && if (entMan.TryGetComponent(item.Owner, out PDAComponent? pda) &&
entMan.TryGetComponent(item.Owner, out PDAComponent? pda) &&
pda.ContainedID != null) pda.ContainedID != null)
{ {
firstIdInPda = pda.ContainedID; foundPDAId = pda.ContainedID;
} }
if (entMan.TryGetComponent(item.Owner, out IdCardComponent? card)) if (entMan.TryGetComponent(item.Owner, out IdCardComponent? card))
@@ -40,32 +39,32 @@ namespace Content.Server.PDA
} }
} }
if (firstIdInPda != null) if (foundPDAId != null) return foundPDAId;
{
return firstIdInPda;
}
IdCardComponent? firstIdInInventory = null; var invSystem = EntitySystem.Get<InventorySystem>();
if (entMan.TryGetComponent(player, out InventoryComponent? inventory)) if (invSystem.TryGetContainerSlotEnumerator(player, out var enumerator))
{ {
foreach (var item in inventory.GetAllHeldItems()) while (enumerator.MoveNext(out var containerSlot))
{ {
if (firstIdInInventory == null && if(!containerSlot.ContainedEntity.HasValue) continue;
entMan.TryGetComponent(item, out PDAComponent? pda) &&
if (entMan.TryGetComponent(containerSlot.ContainedEntity.Value, out PDAComponent? pda) &&
pda.ContainedID != null) pda.ContainedID != null)
{ {
firstIdInInventory = pda.ContainedID; foundPDAId = pda.ContainedID;
} }
if (entMan.TryGetComponent(item, out IdCardComponent? card)) if (entMan.TryGetComponent(containerSlot.ContainedEntity.Value, out IdCardComponent? card))
{ {
return card; return card;
} }
} }
} }
return firstIdInInventory; if (foundPDAId != null) return foundPDAId;
return null;
} }
/// <summary> /// <summary>

View File

@@ -1,12 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Server.Movement.Components; using Content.Server.Movement.Components;
using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.EntitySystems; using Content.Server.Shuttles.EntitySystems;
using Content.Shared.CCVar; using Content.Shared.CCVar;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Maps; using Content.Shared.Maps;
using Content.Shared.Movement; using Content.Shared.Movement;
using Content.Shared.Movement.Components; using Content.Shared.Movement.Components;
@@ -302,9 +301,10 @@ namespace Content.Server.Physics.Controllers
mobMover.StepSoundDistance -= distanceNeeded; mobMover.StepSoundDistance -= distanceNeeded;
if (EntityManager.TryGetComponent<InventoryComponent?>(mover.Owner, out var inventory) var invSystem = EntitySystem.Get<InventorySystem>();
&& inventory.TryGetSlotItem<ItemComponent>(EquipmentSlotDefines.Slots.SHOES, out var item)
&& EntityManager.TryGetComponent<FootstepModifierComponent?>(item.Owner, out var modifier)) if (invSystem.TryGetSlotEntity(mover.Owner, "shoes", out var shoes) &&
EntityManager.TryGetComponent<FootstepModifierComponent>(shoes, out var modifier))
{ {
modifier.PlayFootstep(); modifier.PlayFootstep();
} }

View File

@@ -4,7 +4,6 @@ using System.Linq;
using Content.Server.Atmos.Components; using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.EntitySystems;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Nutrition.Components; using Content.Server.Nutrition.Components;
using Content.Server.Storage.Components; using Content.Server.Storage.Components;
using Content.Server.Stunnable; using Content.Server.Stunnable;
@@ -13,6 +12,7 @@ using Content.Server.Tools.Components;
using Content.Shared.Camera; using Content.Shared.Camera;
using Content.Shared.CombatMode; using Content.Shared.CombatMode;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.PneumaticCannon; using Content.Shared.PneumaticCannon;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.StatusEffect; using Content.Shared.StatusEffect;
@@ -134,7 +134,7 @@ namespace Content.Server.PneumaticCannon
// this overrides the ServerStorageComponent's insertion stuff because // this overrides the ServerStorageComponent's insertion stuff because
// it's not event-based yet and I can't cancel it, so tools and stuff // it's not event-based yet and I can't cancel it, so tools and stuff
// will modify mode/power then get put in anyway // will modify mode/power then get put in anyway
if (EntityManager.TryGetComponent<ItemComponent?>(args.Used, out var item) if (EntityManager.TryGetComponent<SharedItemComponent?>(args.Used, out var item)
&& EntityManager.TryGetComponent<ServerStorageComponent?>(component.Owner, out var storage)) && EntityManager.TryGetComponent<ServerStorageComponent?>(component.Owner, out var storage))
{ {
if (storage.CanInsert(args.Used)) if (storage.CanInsert(args.Used))

View File

@@ -1,9 +1,9 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Weapon.Ranged.Barrels.Components; using Content.Server.Weapon.Ranged.Barrels.Components;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Power; using Content.Shared.Power;
using Robust.Shared.Containers; using Robust.Shared.Containers;
@@ -101,7 +101,7 @@ namespace Content.Server.Power.Components
_heldBattery = null; _heldBattery = null;
if (_entMan.TryGetComponent(user, out HandsComponent? handsComponent)) if (_entMan.TryGetComponent(user, out HandsComponent? handsComponent))
{ {
handsComponent.PutInHandOrDrop(_entMan.GetComponent<ItemComponent>(heldItem)); handsComponent.PutInHandOrDrop(_entMan.GetComponent<SharedItemComponent>(heldItem));
} }
if (_entMan.TryGetComponent(heldItem, out ServerBatteryBarrelComponent? batteryBarrelComponent)) if (_entMan.TryGetComponent(heldItem, out ServerBatteryBarrelComponent? batteryBarrelComponent))

View File

@@ -1,6 +1,5 @@
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Items;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Shared.Console; using Robust.Shared.Console;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;

View File

@@ -1,8 +1,8 @@
using System; using System;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Shared.Audio; using Content.Shared.Audio;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Item;
using Content.Shared.Sound; using Content.Shared.Sound;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Containers; using Robust.Shared.Containers;
@@ -136,7 +136,7 @@ namespace Content.Server.PowerCell.Components
//Dirty(); //Dirty();
if (user != null) if (user != null)
{ {
if (!_entities.TryGetComponent(user, out HandsComponent? hands) || !hands.PutInHand(_entities.GetComponent<ItemComponent>(cell.Owner))) if (!_entities.TryGetComponent(user, out HandsComponent? hands) || !hands.PutInHand(_entities.GetComponent<SharedItemComponent>(cell.Owner)))
{ {
_entities.GetComponent<TransformComponent>(cell.Owner).Coordinates = _entities.GetComponent<TransformComponent>(user.Value).Coordinates; _entities.GetComponent<TransformComponent>(cell.Owner).Coordinates = _entities.GetComponent<TransformComponent>(user.Value).Coordinates;
} }
@@ -164,7 +164,7 @@ namespace Content.Server.PowerCell.Components
public bool InsertCell(EntityUid cell, bool playSound = true) public bool InsertCell(EntityUid cell, bool playSound = true)
{ {
if (Cell != null) return false; if (Cell != null) return false;
if (!_entities.HasComponent<ItemComponent>(cell)) return false; if (!_entities.HasComponent<SharedItemComponent>(cell)) return false;
if (!_entities.TryGetComponent<PowerCellComponent?>(cell, out var cellComponent)) return false; if (!_entities.TryGetComponent<PowerCellComponent?>(cell, out var cellComponent)) return false;
if (cellComponent.CellSize != SlotSize) return false; if (cellComponent.CellSize != SlotSize) return false;
if (!_cellContainer.Insert(cell)) return false; if (!_cellContainer.Insert(cell)) return false;

View File

@@ -1,12 +1,12 @@
using System.Linq; using System.Linq;
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Inventory.Components;
using Content.Server.Items;
using Content.Shared.Access; using Content.Shared.Access;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.PDA; using Content.Shared.PDA;
using Content.Shared.Sandbox; using Content.Shared.Sandbox;
using Robust.Server.Console; using Robust.Server.Console;
@@ -19,7 +19,6 @@ using Robust.Shared.IoC;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Server.Sandbox namespace Content.Server.Sandbox
{ {
@@ -124,14 +123,15 @@ namespace Content.Server.Sandbox
.EnumeratePrototypes<AccessLevelPrototype>() .EnumeratePrototypes<AccessLevelPrototype>()
.Select(p => p.ID).ToArray(); .Select(p => p.ID).ToArray();
if (_entityManager.TryGetComponent(attached, out InventoryComponent? inv) var invSystem = EntitySystem.Get<InventorySystem>();
&& inv.TryGetSlotItem(Slots.IDCARD, out ItemComponent? wornItem))
if (invSystem.TryGetSlotEntity(attached, "id", out var slotEntity))
{ {
if (_entityManager.HasComponent<AccessComponent>(wornItem.Owner)) if (_entityManager.HasComponent<AccessComponent>(slotEntity))
{ {
UpgradeId(wornItem.Owner); UpgradeId(slotEntity.Value);
} }
else if (_entityManager.TryGetComponent(wornItem.Owner, out PDAComponent? pda)) else if (_entityManager.TryGetComponent(slotEntity, out PDAComponent? pda))
{ {
if (pda.ContainedID == null) if (pda.ContainedID == null)
{ {
@@ -139,7 +139,7 @@ namespace Content.Server.Sandbox
if (_entityManager.TryGetComponent(pda.Owner, out ItemSlotsComponent? itemSlots)) if (_entityManager.TryGetComponent(pda.Owner, out ItemSlotsComponent? itemSlots))
{ {
_entityManager.EntitySysManager.GetEntitySystem<ItemSlotsSystem>(). _entityManager.EntitySysManager.GetEntitySystem<ItemSlotsSystem>().
TryInsert(wornItem.Owner, pda.IdSlot, newID, null); TryInsert(slotEntity.Value, pda.IdSlot, newID, null);
} }
} }
else else
@@ -151,9 +151,9 @@ namespace Content.Server.Sandbox
else if (_entityManager.TryGetComponent<HandsComponent?>(attached, out var hands)) else if (_entityManager.TryGetComponent<HandsComponent?>(attached, out var hands))
{ {
var card = CreateFreshId(); var card = CreateFreshId();
if (!_entityManager.TryGetComponent(attached, out inv) || !inv.Equip(Slots.IDCARD, card)) if (!invSystem.TryEquip(attached, card, "id", true, true))
{ {
hands.PutInHandOrDrop(_entityManager.GetComponent<ItemComponent>(card)); hands.PutInHandOrDrop(_entityManager.GetComponent<SharedItemComponent>(card));
} }
} }

View File

@@ -1,8 +1,8 @@
using System; using System;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Items;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Stacks; using Content.Shared.Stacks;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -180,7 +180,7 @@ namespace Content.Server.Stack
if (Split(uid, amount, userTransform.Coordinates, stack) is not {} split) if (Split(uid, amount, userTransform.Coordinates, stack) is not {} split)
return; return;
if (TryComp<HandsComponent>(userUid, out var hands) && TryComp<ItemComponent>(split, out var item)) if (TryComp<HandsComponent>(userUid, out var hands) && TryComp<SharedItemComponent>(split, out var item))
{ {
hands.PutInHandOrDrop(item); hands.PutInHandOrDrop(item);
} }

Some files were not shown because too many files have changed in this diff Show More