diff --git a/Content.Server/Nyanotrasen/Item/PseudoItem/PseudoItemSystem.cs b/Content.Server/Nyanotrasen/Item/PseudoItem/PseudoItemSystem.cs index 03c494332cf..1c1ec1482d4 100644 --- a/Content.Server/Nyanotrasen/Item/PseudoItem/PseudoItemSystem.cs +++ b/Content.Server/Nyanotrasen/Item/PseudoItem/PseudoItemSystem.cs @@ -1,174 +1,43 @@ -using Content.Server.DoAfter; -using Content.Server.Storage.EntitySystems; -using Content.Shared.DoAfter; -using Content.Shared.Hands; -using Content.Shared.IdentityManagement; -using Content.Shared.Item; -using Content.Shared.Item.PseudoItem; +using Content.Shared.IdentityManagement; +using Content.Shared.Nyanotrasen.Item.PseudoItem; using Content.Shared.Storage; -using Content.Shared.Tag; using Content.Shared.Verbs; -using Robust.Shared.Containers; -namespace Content.Server.Item.PseudoItem; +namespace Content.Server.Nyanotrasen.Item.PseudoItem; -public sealed class PseudoItemSystem : EntitySystem +public sealed class PseudoItemSystem : SharedPseudoItemSystem { - // [Dependency] private readonly StorageSystem _storageSystem = default!; - // [Dependency] private readonly ItemSystem _itemSystem = default!; - // [Dependency] private readonly DoAfterSystem _doAfter = default!; - // [Dependency] private readonly TagSystem _tagSystem = default!; - // - // [ValidatePrototypeId] - // private const string PreventTag = "PreventLabel"; - // - // public override void Initialize() - // { - // base.Initialize(); - // SubscribeLocalEvent>(AddInsertVerb); - // SubscribeLocalEvent>(AddInsertAltVerb); - // SubscribeLocalEvent(OnEntRemoved); - // SubscribeLocalEvent(OnGettingPickedUpAttempt); - // SubscribeLocalEvent(OnDropAttempt); - // SubscribeLocalEvent(OnDoAfter); - // SubscribeLocalEvent(OnInsertAttempt); - // } - // - // private void AddInsertVerb(EntityUid uid, PseudoItemComponent component, GetVerbsEvent args) - // { - // if (!args.CanInteract || !args.CanAccess) - // return; - // - // if (component.Active) - // return; - // - // if (!TryComp(args.Target, out var targetStorage)) - // return; - // - // if (component.Size > targetStorage.StorageCapacityMax - targetStorage.StorageUsed) - // return; - // - // if (Transform(args.Target).ParentUid == uid) - // return; - // - // InnateVerb verb = new() - // { - // Act = () => - // { - // TryInsert(args.Target, uid, component, targetStorage); - // }, - // Text = Loc.GetString("action-name-insert-self"), - // Priority = 2 - // }; - // args.Verbs.Add(verb); - // } - // - // private void AddInsertAltVerb(EntityUid uid, PseudoItemComponent component, GetVerbsEvent args) - // { - // if (!args.CanInteract || !args.CanAccess) - // return; - // - // if (args.User == args.Target) - // return; - // - // if (args.Hands == null) - // return; - // - // if (!TryComp(args.Hands.ActiveHandEntity, out var targetStorage)) - // return; - // - // AlternativeVerb verb = new() - // { - // Act = () => - // { - // StartInsertDoAfter(args.User, uid, args.Hands.ActiveHandEntity.Value, component); - // }, - // Text = Loc.GetString("action-name-insert-other", ("target", Identity.Entity(args.Target, EntityManager))), - // Priority = 2 - // }; - // args.Verbs.Add(verb); - // } - // - // private void OnEntRemoved(EntityUid uid, PseudoItemComponent component, EntGotRemovedFromContainerMessage args) - // { - // if (!component.Active) - // return; - // - // RemComp(uid); - // component.Active = false; - // } - // - // private void OnGettingPickedUpAttempt(EntityUid uid, PseudoItemComponent component, - // GettingPickedUpAttemptEvent args) - // { - // if (args.User == args.Item) - // return; - // - // Transform(uid).AttachToGridOrMap(); - // args.Cancel(); - // } - // - // private void OnDropAttempt(EntityUid uid, PseudoItemComponent component, DropAttemptEvent args) - // { - // if (component.Active) - // args.Cancel(); - // } - // - // private void OnDoAfter(EntityUid uid, PseudoItemComponent component, DoAfterEvent args) - // { - // if (args.Handled || args.Cancelled || args.Args.Used == null) - // return; - // - // args.Handled = TryInsert(args.Args.Used.Value, uid, component); - // } - // - // public bool TryInsert(EntityUid storageUid, EntityUid toInsert, PseudoItemComponent component, - // StorageComponent? storage = null) - // { - // if (!Resolve(storageUid, ref storage)) - // return false; - // - // if (component.Size > storage.StorageCapacityMax - storage.StorageUsed) - // return false; - // - // var item = EnsureComp(toInsert); - // _tagSystem.TryAddTag(toInsert, PreventTag); - // _itemSystem.SetSize(toInsert, component.Size, item); - // - // if (!_storageSystem.Insert(storageUid, toInsert, out _, null, storage)) - // { - // component.Active = false; - // RemComp(toInsert); - // return false; - // } - // - // component.Active = true; - // return true; - // } - // - // private void StartInsertDoAfter(EntityUid inserter, EntityUid toInsert, EntityUid storageEntity, - // PseudoItemComponent? pseudoItem = null) - // { - // if (!Resolve(toInsert, ref pseudoItem)) - // return; - // - // var ev = new PseudoItemInsertDoAfterEvent(); - // var args = new DoAfterArgs(EntityManager, inserter, 5f, ev, toInsert, toInsert, storageEntity) - // { - // BreakOnTargetMove = true, - // BreakOnUserMove = true, - // NeedHand = true - // }; - // - // _doAfter.TryStartDoAfter(args); - // } - // - // private void OnInsertAttempt(EntityUid uid, PseudoItemComponent component, - // ContainerGettingInsertedAttemptEvent args) - // { - // if (!component.Active) - // return; - // // This hopefully shouldn't trigger, but this is a failsafe just in case so we dont bluespace them cats - // args.Cancel(); - // } + public override void Initialize() + { + SubscribeLocalEvent>(AddInsertAltVerb); + } + + // For whatever reason, I have to put these in server or the verbs duplicate + private void AddInsertAltVerb(EntityUid uid, PseudoItemComponent component, GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess) + return; + + if (component.Active) + return; + + if (!TryComp(args.Using, out _)) + return; + + // There *should* be a check here to see if we can fit, but I'm not aware of an easy way to do that, so eh, who cares + + if (args.Hands?.ActiveHandEntity == null) + return; + + AlternativeVerb verb = new() + { + Act = () => + { + StartInsertDoAfter(args.User, uid, args.Hands.ActiveHandEntity.Value, component); + }, + Text = Loc.GetString("action-name-insert-other", ("target", Identity.Entity(args.Target, EntityManager))), + Priority = 2 + }; + args.Verbs.Add(verb); + } } diff --git a/Content.Shared/Item/ItemComponent.cs b/Content.Shared/Item/ItemComponent.cs index 9fadfa0783c..0f599ebdbed 100644 --- a/Content.Shared/Item/ItemComponent.cs +++ b/Content.Shared/Item/ItemComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Hands.Components; +using Content.Shared.Nyanotrasen.Item.PseudoItem; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; @@ -12,11 +13,11 @@ namespace Content.Shared.Item; /// [RegisterComponent] [NetworkedComponent] -[Access(typeof(SharedItemSystem)), AutoGenerateComponentState(true)] +[Access(typeof(SharedItemSystem), typeof(SharedPseudoItemSystem)), AutoGenerateComponentState(true)] // DeltaV - Gave PseudoItem access public sealed partial class ItemComponent : Component { [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - [Access(typeof(SharedItemSystem))] + [Access(typeof(SharedItemSystem), typeof(SharedPseudoItemSystem))] // DeltaV - Gave PseudoItem access public ProtoId Size = "Small"; [Access(typeof(SharedItemSystem))] diff --git a/Content.Shared/Nyanotrasen/Item/Components/PseudoItemComponent.cs b/Content.Shared/Nyanotrasen/Item/PseudoItem/PseudoItemComponent.cs similarity index 84% rename from Content.Shared/Nyanotrasen/Item/Components/PseudoItemComponent.cs rename to Content.Shared/Nyanotrasen/Item/PseudoItem/PseudoItemComponent.cs index cad826aa6b9..d3774439d36 100644 --- a/Content.Shared/Nyanotrasen/Item/Components/PseudoItemComponent.cs +++ b/Content.Shared/Nyanotrasen/Item/PseudoItem/PseudoItemComponent.cs @@ -1,8 +1,7 @@ - using Content.Shared.Item; using Robust.Shared.Prototypes; -namespace Content.Shared.Nyanotrasen.Item.Components; +namespace Content.Shared.Nyanotrasen.Item.PseudoItem; /// /// For entities that behave like an item under certain conditions, @@ -21,5 +20,8 @@ public sealed partial class PseudoItemComponent : Component [DataField, AutoNetworkedField] public List? Shape; + [DataField, AutoNetworkedField] + public Vector2i StoredOffset; + public bool Active = false; } diff --git a/Content.Shared/Nyanotrasen/Item/PseudoItem/SharedPseudoItemSystem.cs b/Content.Shared/Nyanotrasen/Item/PseudoItem/SharedPseudoItemSystem.cs new file mode 100644 index 00000000000..934a1e45be1 --- /dev/null +++ b/Content.Shared/Nyanotrasen/Item/PseudoItem/SharedPseudoItemSystem.cs @@ -0,0 +1,155 @@ +using Content.Shared.DoAfter; +using Content.Shared.Hands; +using Content.Shared.IdentityManagement; +using Content.Shared.Interaction.Events; +using Content.Shared.Item; +using Content.Shared.Item.PseudoItem; +using Content.Shared.Storage; +using Content.Shared.Storage.EntitySystems; +using Content.Shared.Tag; +using Content.Shared.Verbs; +using Robust.Shared.Containers; + +namespace Content.Shared.Nyanotrasen.Item.PseudoItem; + +public class SharedPseudoItemSystem : EntitySystem +{ + [Dependency] private readonly SharedStorageSystem _storageSystem = default!; + [Dependency] private readonly SharedItemSystem _itemSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly TagSystem _tagSystem = default!; + + [ValidatePrototypeId] + private const string PreventTag = "PreventLabel"; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent>(AddInsertVerb); + SubscribeLocalEvent(OnEntRemoved); + SubscribeLocalEvent(OnGettingPickedUpAttempt); + SubscribeLocalEvent(OnDropAttempt); + SubscribeLocalEvent(OnDoAfter); + SubscribeLocalEvent(OnInsertAttempt); + SubscribeLocalEvent(OnInteractAttempt); + } + + private void AddInsertVerb(EntityUid uid, PseudoItemComponent component, GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess) + return; + + if (component.Active) + return; + + if (!TryComp(args.Target, out var targetStorage)) + return; + + // There *should* be a check here to see if we can fit, but I'm not aware of an easy way to do that, so eh, who cares + + if (Transform(args.Target).ParentUid == uid) + return; + + InnateVerb verb = new() + { + Act = () => + { + TryInsert(args.Target, uid, component, targetStorage); + }, + Text = Loc.GetString("action-name-insert-self"), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void OnEntRemoved(EntityUid uid, PseudoItemComponent component, EntGotRemovedFromContainerMessage args) + { + if (!component.Active) + return; + + RemComp(uid); + component.Active = false; + } + + private void OnGettingPickedUpAttempt(EntityUid uid, PseudoItemComponent component, + GettingPickedUpAttemptEvent args) + { + if (args.User == args.Item) + return; + + Transform(uid).AttachToGridOrMap(); + args.Cancel(); + } + + private void OnDropAttempt(EntityUid uid, PseudoItemComponent component, DropAttemptEvent args) + { + if (component.Active) + args.Cancel(); + } + + private void OnDoAfter(EntityUid uid, PseudoItemComponent component, DoAfterEvent args) + { + if (args.Handled || args.Cancelled || args.Args.Used == null) + return; + + args.Handled = TryInsert(args.Args.Used.Value, uid, component); + } + + public bool TryInsert(EntityUid storageUid, EntityUid toInsert, PseudoItemComponent component, + StorageComponent? storage = null) + { + if (!Resolve(storageUid, ref storage)) + return false; + + // Again, here we really should check if the item will fit, but at least insert takes care of it for us by failing if not /shrug + + var itemComp = new ItemComponent { Size = component.Size, Shape = component.Shape, StoredOffset = component.StoredOffset }; + AddComp(toInsert, itemComp); + _itemSystem.VisualsChanged(toInsert); + + _tagSystem.TryAddTag(toInsert, PreventTag); + + if (!_storageSystem.Insert(storageUid, toInsert, out _, null, storage)) + { + component.Active = false; + RemComp(toInsert); + return false; + } + + component.Active = true; + return true; + } + + protected internal void StartInsertDoAfter(EntityUid inserter, EntityUid toInsert, EntityUid storageEntity, + PseudoItemComponent? pseudoItem = null) + { + if (!Resolve(toInsert, ref pseudoItem)) + return; + + var ev = new PseudoItemInsertDoAfterEvent(); + var args = new DoAfterArgs(EntityManager, inserter, 5f, ev, toInsert, toInsert, storageEntity) + { + BreakOnTargetMove = true, + BreakOnUserMove = true, + NeedHand = true + }; + + _doAfter.TryStartDoAfter(args); + } + + private void OnInsertAttempt(EntityUid uid, PseudoItemComponent component, + ContainerGettingInsertedAttemptEvent args) + { + if (!component.Active) + return; + // This hopefully shouldn't trigger, but this is a failsafe just in case so we dont bluespace them cats + args.Cancel(); + } + + // Prevents moving within the bag :) + private void OnInteractAttempt(EntityUid uid, PseudoItemComponent component, InteractionAttemptEvent args) + { + if (args.Uid == args.Target && component.Active) + args.Cancel(); + } +} diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index eb81a78e3ef..c00df042653 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -10,9 +10,8 @@ using Content.Shared.Implants.Components; using Content.Shared.Interaction; using Content.Shared.Item; -using Content.Shared.Item.PseudoItem; using Content.Shared.Lock; -using Content.Shared.Nyanotrasen.Item.Components; +using Content.Shared.Nyanotrasen.Item.PseudoItem; using Content.Shared.Placeable; using Content.Shared.Popups; using Content.Shared.Stacks; diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Species/felinid.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Species/felinid.yml index e2e15dcfa95..5110470a5d6 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Species/felinid.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Species/felinid.yml @@ -48,8 +48,11 @@ - type: Stamina critThreshold: 85 - type: PseudoItem + storedOffset: 0,17 shape: - - 0,0,5,1 + - 0,0,1,4 + - 0,2,3,4 + - 4,0,5,4 - type: Vocal wilhelm: "/Audio/Nyanotrasen/Voice/Felinid/cat_wilhelm.ogg" sounds: