using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; using System.Linq; namespace Content.Shared.Placeable; /// /// Tracks placed entities /// Subscribe to or to do things when items or placed or removed. /// public sealed class ItemPlacerSystem : EntitySystem { [Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnStartCollide); SubscribeLocalEvent(OnEndCollide); } private void OnStartCollide(EntityUid uid, ItemPlacerComponent comp, ref StartCollideEvent args) { if (comp.Whitelist != null && !comp.Whitelist.IsValid(args.OtherEntity)) return; // Disallow sleeping so we can detect when entity is removed from the heater. _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, false); var count = comp.PlacedEntities.Count; if (comp.MaxEntities == 0 || count < comp.MaxEntities) { comp.PlacedEntities.Add(args.OtherEntity); var ev = new ItemPlacedEvent(args.OtherEntity); RaiseLocalEvent(uid, ref ev); } if (comp.MaxEntities > 0 && count >= (comp.MaxEntities - 1)) { // Don't let any more items be placed if it's reached its limit. _placeableSurface.SetPlaceable(uid, false); } } private void OnEndCollide(EntityUid uid, ItemPlacerComponent comp, ref EndCollideEvent args) { // Re-allow sleeping. _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, true); comp.PlacedEntities.Remove(args.OtherEntity); var ev = new ItemRemovedEvent(args.OtherEntity); RaiseLocalEvent(uid, ref ev); _placeableSurface.SetPlaceable(uid, true); } } /// /// Raised on the when an item is placed and it is under the item limit. /// [ByRefEvent] public record struct ItemPlacedEvent(EntityUid OtherEntity); /// /// Raised on the when an item is removed from it. /// [ByRefEvent] public record struct ItemRemovedEvent(EntityUid OtherEntity);