public void ApplyGameStatePost(GameStateMapData data)
        {
            DebugTools.Assert(_netManager.IsClient, "Only the client should call this.");

            foreach (var grid in data.DeletedGrids)
            {
                if (_grids.ContainsKey(grid))
                {
                    DeleteGrid(grid);
                }
            }

            foreach (var map in data.DeletedMaps)
            {
                if (_maps.ContainsKey(map))
                {
                    DeleteMap(map);
                }
            }
        }
        public void ApplyGameStatePre(GameStateMapData data)
        {
            DebugTools.Assert(_netManager.IsClient, "Only the client should call this.");

            // First we need to figure out all the NEW MAPS.
            // And make their default grids too.
            foreach (var(mapId, gridId) in data.CreatedMaps)
            {
                if (_maps.ContainsKey(mapId))
                {
                    continue;
                }
                var gridCreation = data.CreatedGrids[gridId];
                DebugTools.Assert(gridCreation.IsTheDefault);

                var newMap = new Map(this, mapId);
                _maps.Add(mapId, newMap);
                MapCreated?.Invoke(this, new MapEventArgs(newMap));
                newMap.DefaultGrid = CreateGrid(newMap.Index, gridId, gridCreation.ChunkSize, gridCreation.SnapSize);
            }

            // Then make all the other grids.
            foreach (var(gridId, creationDatum) in data.CreatedGrids)
            {
                if (creationDatum.IsTheDefault || _grids.ContainsKey(gridId))
                {
                    continue;
                }

                CreateGrid(data.GridData[gridId].Coordinates.MapId, gridId, creationDatum.ChunkSize,
                           creationDatum.SnapSize);
            }

            SuppressOnTileChanged = true;
            // Ok good all the grids and maps exist now.
            foreach (var(gridId, gridDatum) in data.GridData)
            {
                var grid = _grids[gridId];
                if (grid.MapID != gridDatum.Coordinates.MapId)
                {
                    throw new NotImplementedException("Moving grids between maps is not yet implemented");
                }

                grid.WorldPosition = gridDatum.Coordinates.Position;

                var modified = new List <(MapIndices position, Tile tile)>();
                foreach (var chunkData in gridDatum.ChunkData)
                {
                    var chunk = grid.GetChunk(chunkData.Index);
                    DebugTools.Assert(chunkData.TileData.Length == grid.ChunkSize * grid.ChunkSize);

                    var counter = 0;
                    for (ushort x = 0; x < grid.ChunkSize; x++)
                    {
                        for (ushort y = 0; y < grid.ChunkSize; y++)
                        {
                            var tile = chunkData.TileData[counter++];
                            if (chunk.GetTile(x, y).Tile != tile)
                            {
                                chunk.SetTile(x, y, tile);
                                modified.Add((new MapIndices(chunk.X * grid.ChunkSize + x, chunk.Y * grid.ChunkSize + y), tile));
                            }
                        }
                    }
                }

                if (modified.Count != 0)
                {
                    GridChanged?.Invoke(this, new GridChangedEventArgs(grid, modified));
                }
            }

            SuppressOnTileChanged = false;
        }