using System; using System.Collections.Generic; using System.Linq; using Robust.Client.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects.Components; using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; namespace Robust.Client.GameObjects { /// /// Manager for entities -- controls things like template loading and instantiation /// public sealed class ClientEntityManager : EntityManager, IClientEntityManager, IDisposable { #pragma warning disable 649 [Dependency] private readonly IMapManager _mapManager; #pragma warning restore 649 private int NextClientEntityUid = EntityUid.ClientUid + 1; public IEnumerable GetEntitiesInRange(GridCoordinates position, float range) { var aabb = new Box2(position.Position - new Vector2(range / 2, range / 2), position.Position + new Vector2(range / 2, range / 2)); return GetEntitiesIntersecting(_mapManager.GetGrid(position.GridID).ParentMapId, aabb); } public IEnumerable GetEntitiesIntersecting(MapId mapId, Box2 position) { foreach (var entity in GetEntities()) { var transform = entity.Transform; if (transform.MapID != mapId) continue; if (entity.TryGetComponent(out var component)) { if (position.Intersects(component.WorldAABB)) yield return entity; } else { if (position.Contains(transform.WorldPosition)) { yield return entity; } } } } public IEnumerable GetEntitiesIntersecting(MapId mapId, Vector2 position) { foreach (var entity in GetEntities()) { var transform = entity.Transform; if (transform.MapID != mapId) continue; if (entity.TryGetComponent(out var component)) { if (component.WorldAABB.Contains(position)) yield return entity; } else { if (FloatMath.CloseTo(transform.GridPosition.X, position.X) && FloatMath.CloseTo(transform.GridPosition.Y, position.Y)) { yield return entity; } } } } public bool AnyEntitiesIntersecting(MapId mapId, Box2 box) { foreach (var entity in GetEntities()) { var transform = entity.Transform; if (transform.MapID != mapId) continue; if (entity.TryGetComponent(out var component)) { if (box.Intersects(component.WorldAABB)) return true; } else { if (box.Contains(transform.WorldPosition)) { return true; } } } return false; } public override void Startup() { base.Startup(); if (Started) { throw new InvalidOperationException("Startup() called multiple times"); } EntitySystemManager.Initialize(); Started = true; } public void ApplyEntityStates(List curEntStates, IEnumerable deletions, List nextEntStates) { var toApply = new Dictionary(); var toInitialize = new List(); deletions = deletions ?? new EntityUid[0]; if (curEntStates != null && curEntStates.Count != 0) { foreach (var es in curEntStates) { //Known entities if (Entities.TryGetValue(es.Uid, out var entity)) { toApply.Add(entity, (es, null)); } else //Unknown entities { var metaState = (MetaDataComponentState)es.ComponentStates.First(c => c.NetID == NetIDs.META_DATA); var newEntity = CreateEntity(metaState.PrototypeId, es.Uid); toApply.Add(newEntity, (es, null)); toInitialize.Add(newEntity); } } } if (nextEntStates != null && nextEntStates.Count != 0) { foreach (var es in nextEntStates) { if (Entities.TryGetValue(es.Uid, out var entity)) { if (toApply.TryGetValue(entity, out var state)) { toApply[entity] = (state.Item1, es); } else { toApply[entity] = (null, es); } } } } // Make sure this is done after all entities have been instantiated. foreach (var kvStates in toApply) { var ent = kvStates.Key; ((Entity)ent).HandleEntityState(kvStates.Value.Item1, kvStates.Value.Item2); } foreach (var id in deletions) { DeleteEntity(id); } foreach (var entity in toInitialize) { InitializeEntity(entity); } foreach (var entity in toInitialize) { StartEntity(entity); } } public void Dispose() { Shutdown(); } public override IEntity SpawnEntity(string protoName) { var ent = CreateEntity(protoName, NewClientEntityUid()); InitializeAndStartEntity(ent); return ent; } public override IEntity SpawnEntityNoMapInit(string protoName) { return SpawnEntity(protoName); } public override IEntity SpawnEntityAt(string entityType, GridCoordinates coordinates) { var entity = CreateEntity(entityType, NewClientEntityUid()); entity.Transform.GridPosition = coordinates; InitializeAndStartEntity(entity); return entity; } private EntityUid NewClientEntityUid() { return new EntityUid(NextClientEntityUid++); } } }