namespace TanksServer.GameLogic; internal sealed class MapEntityManager( ILogger<MapEntityManager> logger, IOptions<GameRules> options ) { private readonly GameRules _rules = options.Value; private readonly HashSet<Bullet> _bullets = []; private readonly HashSet<PowerUp> _powerUps = []; private readonly Dictionary<Player, Tank> _playerTanks = []; private readonly TimeSpan _bulletTimeout = TimeSpan.FromMilliseconds(options.Value.BulletTimeoutMs); public IEnumerable<Bullet> Bullets => _bullets; public IEnumerable<Tank> Tanks => _playerTanks.Values; public IEnumerable<PowerUp> PowerUps => _powerUps; public void SpawnBullet(Player tankOwner, FloatPosition position, double rotation, MagazineType type) { var speed = _rules.BulletSpeed * (type.HasFlag(MagazineType.Fast) ? 2 : 1); _bullets.Add(new Bullet { Owner = tankOwner, Position = position, Rotation = rotation, IsExplosive = type.HasFlag(MagazineType.Explosive), Timeout = DateTime.Now + _bulletTimeout, OwnerCollisionAfter = DateTime.Now + TimeSpan.FromSeconds(1), Speed = speed, IsSmart = type.HasFlag(MagazineType.Smart) }); } public void RemoveWhere(Predicate<Bullet> predicate) => _bullets.RemoveWhere(predicate); public void SpawnTank(Player player, FloatPosition position) { var tank = new Tank { Owner = player, Position = position, Rotation = Random.Shared.NextDouble(), Magazine = new Magazine(MagazineType.Basic, 0, _rules.MagazineSize) }; _playerTanks[player] = tank; logger.LogInformation("Tank added for player {}", player.Name); } public void SpawnPowerUp(FloatPosition position, PowerUpType type, MagazineType? magazineType) { var powerUp = new PowerUp { Position = position, Type = type, MagazineType = magazineType }; _powerUps.Add(powerUp); } public void RemoveWhere(Predicate<PowerUp> predicate) => _powerUps.RemoveWhere(predicate); public void Remove(Tank tank) { logger.LogInformation("Tank removed for player {}", tank.Owner.Name); _playerTanks.Remove(tank.Owner); } public Tank? GetCurrentTankOfPlayer(Player player) => _playerTanks.GetValueOrDefault(player); public IEnumerable<IMapEntity> AllEntities => Bullets .Cast<IMapEntity>() .Concat(Tanks) .Concat(PowerUps); }