using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Server.Storage.EntitySystems; using Content.Shared._NF.CrateMachine; using Content.Shared._NF.CrateMachine.Components; using Content.Shared.Maps; using Robust.Server.GameObjects; using Robust.Shared.Map; namespace Content.Server._NF.CrateMachine; /// /// The crate machine system can be used to make a crate machine open and spawn crates. /// When calling , the machine will open the door and give a callback to the given /// public sealed partial class CrateMachineSystem : SharedCrateMachineSystem { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly EntityStorageSystem _storage = default!; [Dependency] private readonly TransformSystem _transform = default!; /// /// Checks if there is a crate on the crate machine. /// /// The Uid of the crate machine /// The crate machine component /// Ignores animation checks /// False if not occupied, true if it is. public bool IsOccupied(EntityUid crateMachineUid, CrateMachineComponent component, bool ignoreAnimation = false) { if (!TryComp(crateMachineUid, out TransformComponent? crateMachineTransform)) return true; var tileRef = crateMachineTransform.Coordinates.GetTileRef(EntityManager, _mapManager); if (tileRef == null) return true; if (!ignoreAnimation && (component.OpeningTimeRemaining > 0 || component.ClosingTimeRemaining > 0f)) return true; // Finally check if there is a crate intersecting the crate machine. return _lookup.GetLocalEntitiesIntersecting(tileRef.Value, flags: LookupFlags.All | LookupFlags.Approximate) .Any(entity => MetaData(entity).EntityPrototype?.ID == component.CratePrototype); } /// /// Find the nearest unoccupied anchored crate machine on the same grid. /// /// The Uid of the entity to find the nearest crate machine from /// The maximum distance to search for a crate machine /// The Uid of the nearest unoccupied crate machine, or null if none found /// True if a crate machine was found, false if not public bool FindNearestUnoccupied(EntityUid from, int maxDistance, [NotNullWhen(true)] out EntityUid? machineUid) { machineUid = null; if (maxDistance < 0) return false; var fromXform = Transform(from); if (fromXform.GridUid == null) return false; var crateMachineQuery = AllEntityQuery(); while (crateMachineQuery.MoveNext(out var crateMachineUid, out var comp, out var compXform)) { // Skip crate machines that aren't mounted on a grid. if (compXform.GridUid == null) continue; // Skip crate machines that are not on the same grid. if (compXform.GridUid != fromXform.GridUid) continue; var isTooFarAway = !_transform.InRange(compXform.Coordinates, fromXform.Coordinates, maxDistance); var isBusy = IsOccupied(crateMachineUid, comp); if (!compXform.Anchored || isTooFarAway || isBusy) { continue; } machineUid = crateMachineUid; return true; } return false; } /// /// Convenience function that simply spawns a crate and returns the uid. /// /// The Uid of the crate machine /// The crate machine component /// The Uid of the spawned crate public EntityUid SpawnCrate(EntityUid uid, CrateMachineComponent component) { return Spawn(component.CratePrototype, Transform(uid).Coordinates); } /// /// Convenience function that simply inserts a entity into the container entity and relieve the caller of /// using the storage system reference. /// /// The Uid of the crate machine /// The Uid of the container public void InsertIntoCrate(EntityUid uid, EntityUid container) { _storage.Insert(uid, container); } }