public async IAsyncEnumerable <Image> Paint(string map)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings (){ Map = map });

            var server = pairTracker.Pair.Server;
            var client = pairTracker.Pair.Client;

            Console.WriteLine($"Loaded client and server in {(int) stopwatch.Elapsed.TotalMilliseconds} ms");

            stopwatch.Restart();

            var cEntityManager = client.ResolveDependency <IClientEntityManager>();
            var cPlayerManager = client.ResolveDependency <Robust.Client.Player.IPlayerManager>();

            await client.WaitPost(() =>
            {
                if (cEntityManager.TryGetComponent(cPlayerManager.LocalPlayer !.ControlledEntity !, out Robust.Client.GameObjects.SpriteComponent? sprite))
                {
                    sprite.Visible = false;
                }
            });

            var sEntityManager = server.ResolveDependency <IServerEntityManager>();
            var sPlayerManager = server.ResolveDependency <IPlayerManager>();

            await server.WaitPost(() =>
            {
                if (sEntityManager.TryGetComponent(sPlayerManager.ServerSessions.Single().AttachedEntity !, out SpriteComponent? sprite))
                {
                    sprite.Visible = false;
                }
            });

            await PoolManager.RunTicksSync(pairTracker.Pair, 10);

            await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());

            var sMapManager = server.ResolveDependency <IMapManager>();

            var tilePainter   = new TilePainter(client, server);
            var entityPainter = new GridPainter(client, server);

            IMapGrid[] grids = null !;

            await server.WaitPost(() =>
            {
                var playerEntity = sPlayerManager.ServerSessions.Single().AttachedEntity;

                if (playerEntity.HasValue)
                {
                    sEntityManager.DeleteEntity(playerEntity.Value);
                }

                grids = sMapManager.GetAllMapGrids(new MapId(1)).ToArray();

                foreach (var grid in grids)
                {
                    grid.WorldRotation = Angle.Zero;
                }
            });

            await PoolManager.RunTicksSync(pairTracker.Pair, 10);

            await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());

            foreach (var grid in grids)
            {
                // Skip empty grids
                if (grid.LocalAABB.IsEmpty())
                {
                    Console.WriteLine($"Warning: Grid {grid.Index} was empty. Skipping image rendering.");
                    continue;
                }

                var tileXSize = grid.TileSize * TilePainter.TileImageSize;
                var tileYSize = grid.TileSize * TilePainter.TileImageSize;

                var bounds = grid.LocalAABB;

                var left   = bounds.Left;
                var right  = bounds.Right;
                var top    = bounds.Top;
                var bottom = bounds.Bottom;

                var w = (int)Math.Ceiling(right - left) * tileXSize;
                var h = (int)Math.Ceiling(top - bottom) * tileYSize;

                var gridCanvas = new Image <Rgba32>(w, h);

                await server.WaitPost(() =>
                {
                    tilePainter.Run(gridCanvas, grid);
                    entityPainter.Run(gridCanvas, grid);

                    gridCanvas.Mutate(e => e.Flip(FlipMode.Vertical));
                });

                yield return(gridCanvas);
            }

            // We don't care if it fails as we have already saved the images.
            try
            {
                await pairTracker.CleanReturnAsync();
            }
            catch
            {
                // ignored
            }
        }
        public async IAsyncEnumerable <Image> Paint(string map)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            var clientOptions = new ClientContentIntegrationOption
            {
                CVarOverrides =
                {
                    [CVars.NetPVS.Name] = "false"
                },
                Pool            = false,
                FailureLogLevel = LogLevel.Fatal
            };

            var serverOptions = new ServerContentIntegrationOption
            {
                CVarOverrides =
                {
                    [CCVars.GameMap.Name] = map,
                    [CVars.NetPVS.Name]   = "false"
                },
                Pool            = false,
                FailureLogLevel = LogLevel.Fatal
            };

            var(client, server) = await StartConnectedServerClientPair(clientOptions, serverOptions);

            await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());

            await RunTicksSync(client, server, 10);

            await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());

            Console.WriteLine($"Loaded client and server in {(int) stopwatch.Elapsed.TotalMilliseconds} ms");

            stopwatch.Restart();

            var cEntityManager = client.ResolveDependency <IClientEntityManager>();
            var cPlayerManager = client.ResolveDependency <Robust.Client.Player.IPlayerManager>();

            await client.WaitPost(() =>
            {
                if (cEntityManager.TryGetComponent(cPlayerManager.LocalPlayer !.ControlledEntity !, out Robust.Client.GameObjects.SpriteComponent? sprite))
                {
                    sprite.Visible = false;
                }
            });

            var sEntityManager = server.ResolveDependency <IServerEntityManager>();
            var sPlayerManager = server.ResolveDependency <IPlayerManager>();

            await server.WaitPost(() =>
            {
                if (sEntityManager.TryGetComponent(sPlayerManager.ServerSessions.Single().AttachedEntity !, out SpriteComponent? sprite))
                {
                    sprite.Visible = false;
                }
            });

            await RunTicksSync(client, server, 10);

            await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());

            var sMapManager = server.ResolveDependency <IMapManager>();

            var tilePainter   = new TilePainter(client, server);
            var entityPainter = new GridPainter(client, server);

            IMapGrid[] grids = null !;

            await server.WaitPost(() =>
            {
                var playerEntity = sPlayerManager.ServerSessions.Single().AttachedEntity;

                if (playerEntity.HasValue)
                {
                    sEntityManager.DeleteEntity(playerEntity.Value);
                }

                grids = sMapManager.GetAllMapGrids(new MapId(1)).ToArray();

                foreach (var grid in grids)
                {
                    grid.WorldRotation = Angle.Zero;
                }
            });

            await RunTicksSync(client, server, 10);

            await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());

            foreach (var grid in grids)
            {
                var tileXSize = grid.TileSize * TilePainter.TileImageSize;
                var tileYSize = grid.TileSize * TilePainter.TileImageSize;

                var bounds = grid.LocalBounds;

                var left   = bounds.Left;
                var right  = bounds.Right;
                var top    = bounds.Top;
                var bottom = bounds.Bottom;

                var w = (int)Math.Ceiling(right - left) * tileXSize;
                var h = (int)Math.Ceiling(top - bottom) * tileYSize;

                var gridCanvas = new Image <Rgba32>(w, h);

                await server.WaitPost(() =>
                {
                    tilePainter.Run(gridCanvas, grid);
                    entityPainter.Run(gridCanvas, grid);

                    gridCanvas.Mutate(e => e.Flip(FlipMode.Vertical));
                });

                yield return(gridCanvas);
            }

            // We don't care if it fails as we have already saved the images.
            try
            {
                await OneTimeTearDown();
            }
            catch
            {
                // ignored
            }
        }