using System.Numerics; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Storage; using Content.Shared.Storage.Components; namespace Content.Shared.Placeable; public sealed class PlaceableSurfaceSystem : EntitySystem { [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnAfterInteractUsing); SubscribeLocalEvent(OnStorageInteractUsingAttempt); SubscribeLocalEvent(OnStorageAfterOpen); SubscribeLocalEvent(OnStorageAfterClose); } public void SetPlaceable(EntityUid uid, bool isPlaceable, PlaceableSurfaceComponent? surface = null) { if (!Resolve(uid, ref surface, false)) return; if (surface.IsPlaceable == isPlaceable) return; surface.IsPlaceable = isPlaceable; Dirty(uid, surface); } public void SetPlaceCentered(EntityUid uid, bool placeCentered, PlaceableSurfaceComponent? surface = null) { if (!Resolve(uid, ref surface)) return; surface.PlaceCentered = placeCentered; Dirty(uid, surface); } public void SetPositionOffset(EntityUid uid, Vector2 offset, PlaceableSurfaceComponent? surface = null) { if (!Resolve(uid, ref surface)) return; surface.PositionOffset = offset; Dirty(uid, surface); } private void OnAfterInteractUsing(EntityUid uid, PlaceableSurfaceComponent surface, AfterInteractUsingEvent args) { if (args.Handled || !args.CanReach) return; if (!surface.IsPlaceable) return; // 99% of the time they want to dump the stuff inside on the table, they can manually place with q if they really need to. // Just causes prediction CBT otherwise. if (HasComp(args.Used)) return; if (!_handsSystem.TryDrop(args.User, args.Used)) return; _transformSystem.SetCoordinates(args.Used, surface.PlaceCentered ? Transform(uid).Coordinates.Offset(surface.PositionOffset) : args.ClickLocation); args.Handled = true; } private void OnStorageInteractUsingAttempt(Entity ent, ref StorageInteractUsingAttemptEvent args) { args.Cancelled = true; } private void OnStorageAfterOpen(Entity ent, ref StorageAfterOpenEvent args) { SetPlaceable(ent.Owner, true, ent.Comp); } private void OnStorageAfterClose(Entity ent, ref StorageAfterCloseEvent args) { SetPlaceable(ent.Owner, false, ent.Comp); } }