using Microsoft.Xna.Framework; using System; using System.Collections.Generic; namespace Barotrauma { class EntityGrid { private List[,] entities; private Rectangle limits; private float cellSize; public readonly Submarine Submarine; public EntityGrid(Submarine submarine, float cellSize) { this.limits = submarine.Borders; this.Submarine = submarine; this.cellSize = cellSize; entities = new List[(int)Math.Ceiling(limits.Width / cellSize), (int)Math.Ceiling(limits.Height / cellSize)]; for (int x = 0; x < entities.GetLength(0); x++) { for (int y = 0; y < entities.GetLength(1); y++) { entities[x, y] = new List(); } } } public void InsertEntity(MapEntity entity) { Rectangle rect = entity.Rect; //if (Submarine.Loaded != null) rect.Offset(-Submarine.HiddenSubPosition); Rectangle indices = GetIndices(rect); if (indices.Width < 0 || indices.X >= entities.GetLength(0) || indices.Height < 0 || indices.Y >= entities.GetLength(1)) { DebugConsole.ThrowError("Error in EntityGrid.InsertEntity: " + entity + " is outside the grid"); return; } for (int x = Math.Max(indices.X, 0); x <= Math.Min(indices.Width, entities.GetLength(0)-1); x++) { for (int y = Math.Max(indices.Y,0); y <= Math.Min(indices.Height, entities.GetLength(1)-1); y++) { entities[x, y].Add(entity); } } } public void RemoveEntity(MapEntity entity) { for (int x = 0; x < entities.GetLength(0); x++) { for (int y = 0; y < entities.GetLength(1); y++) { if (entities[x, y].Contains(entity)) entities[x, y].Remove(entity); } } } public void Clear() { for (int x = 0; x < entities.GetLength(0); x++) { for (int y = 0; y < entities.GetLength(1); y++) { entities[x, y].Clear(); } } } public static List GetEntities(List entityGrids, Vector2 position, bool useWorldCoordinates = true) { List entities = new List(); foreach (EntityGrid entityGrid in entityGrids) { Vector2 transformedPosition = position; if (useWorldCoordinates) { transformedPosition -= entityGrid.Submarine.Position; } entities.AddRange(entityGrid.GetEntities(transformedPosition)); } return entities; } public List GetEntities(Vector2 position) { if (!MathUtils.IsValid(position)) new List(); if (Submarine != null) position -= Submarine.HiddenSubPosition; Point indices = GetIndices(position); if (indices.X < 0 || indices.Y < 0 || indices.X >= entities.GetLength(0) || indices.Y >= entities.GetLength(1)) { return new List(); } return entities[indices.X, indices.Y]; } public Rectangle GetIndices(Rectangle rect) { Rectangle indices = Rectangle.Empty; indices.X = (int)Math.Floor((rect.X - limits.X) / cellSize); indices.Y = (int)Math.Floor((limits.Y - rect.Y) / cellSize); indices.Width = (int)Math.Floor((rect.Right - limits.X) / cellSize); indices.Height = (int)Math.Floor((limits.Y - (rect.Y - rect.Height)) / cellSize); return indices; } public Point GetIndices(Vector2 position) { return new Point( (int)Math.Floor((position.X - limits.X) / cellSize), (int)Math.Floor((limits.Y - position.Y) / cellSize)); } } }