can you significantly reduce chunk creation speeds and all related processing? generally optimize the code for performance. give the full optimized and compacted code.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using Newtonsoft.Json;
using System.IO;
using System.Linq;
using System;

public class BlockFetcher : MonoBehaviour
{
private string serverUrl = "http://localhost:8000/blocks";
public string texturePath = "Assets/Textures";
public Material blockMaterial;
[Tooltip(
"The name of the texture file to use when a block's texture is not found (without .png extension)"
)]
public string defaultTextureName = "missing_texture";
private const int MAX_VERTICES_PER_CHUNK = 65000; // Slightly below Unity's limit of 65,535
private List meshChunks = new List();


public string[] woodTypes;
public Mesh slabMesh;
public Mesh fenceMesh;
public Mesh stairMesh;

private class MeshChunk
{
    public List<Vector3> vertices;
    public List<int> triangles;
    public List<Vector2> uvs;
    public bool isFull => vertices.Count + 4 >= MAX_VERTICES_PER_CHUNK; // +4 for next quad

    public MeshChunk()
    {
        int capacity = MAX_VERTICES_PER_CHUNK + 4;
        vertices = new List<Vector3>(capacity);
        uvs = new List<Vector2>(capacity);
        triangles = new List<int>(capacity * 2); // Estimate triangle count
    }
}

[System.Serializable]
public class BlockTextureConfig
{
    public string blockName;
    public string top;
    public string bottom;
    public string front;
    public string back;
    public string left;
    public string right;
    public string side;
    public bool isBillboard;
    public Mesh customMesh;
    public void SetDefaults(string defaultName)
    {
        if (string.IsNullOrEmpty(top)) top = defaultName;
        if (string.IsNullOrEmpty(bottom)) bottom = defaultName;
        if (!string.IsNullOrEmpty(side))
        {
            front = back = left = right = side;
        }
        else
        {
            if (string.IsNullOrEmpty(front)) front = defaultName;
            if (string.IsNullOrEmpty(back)) back = defaultName;
            if (string.IsNullOrEmpty(left)) left = defaultName;
            if (string.IsNullOrEmpty(right)) right = defaultName;
        }
    }
}

[System.Serializable]
public class BlockTintConfig
{
    public string blockName;
    public Color tintColor;
    public string maskName;

    public BlockTintConfig(string blockName, Color tintColor, string maskName = null)
    {
        this.blockName = blockName;
        this.tintColor = tintColor;
        this.maskName = maskName;
    }
}

public BlockTextureConfig[] blockConfigs;
public BlockTintConfig[] blockTintConfigs;

private Texture2D textureAtlas;
private List<BlockData> blockDataList;
private Rect[] atlasRects;
private Dictionary<string, int> blockNameToTextureIndex = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
private Dictionary<string, BlockTextureConfig> blockConfigMap = new Dictionary<string, BlockTextureConfig>(StringComparer.OrdinalIgnoreCase);
private int defaultTextureIndex;
private Dictionary<int, Vector2[]> uvCache = new Dictionary<int, Vector2[]>();

[System.Serializable]
public class BlockData
{
    public string block_name;
    public int x;
    public int y;
    public int z;
    public string direction;
}

private static readonly Vector3[,] faceVertices =
{
    {
        new Vector3(-0.5f, -0.5f, -0.5f),
        new Vector3( 0.5f, -0.5f, -0.5f),
        new Vector3( 0.5f,  0.5f, -0.5f),
        new Vector3(-0.5f,  0.5f, -0.5f)
    },
    {
        new Vector3(-0.5f, -0.5f, 0.5f),
        new Vector3( 0.5f, -0.5f, 0.5f),
        new Vector3( 0.5f,  0.5f, 0.5f),
        new Vector3(-0.5f,  0.5f, 0.5f)
    },
    {
        new Vector3(-0.5f,  0.5f, -0.5f),
        new Vector3( 0.5f,  0.5f, -0.5f),
        new Vector3( 0.5f,  0.5f,  0.5f),
        new Vector3(-0.5f,  0.5f,  0.5f)
    },
    {
        new Vector3(-0.5f, -0.5f, -0.5f),
        new Vector3( 0.5f, -0.5f, -0.5f),
        new Vector3( 0.5f, -0.5f,  0.5f),
        new Vector3(-0.5f, -0.5f,  0.5f)
    },
    {
        new Vector3(-0.5f, -0.5f, -0.5f),
        new Vector3(-0.5f, -0.5f,  0.5f),
        new Vector3(-0.5f,  0.5f,  0.5f),
        new Vector3(-0.5f,  0.5f, -0.5f)
    },
    {
        new Vector3( 0.5f, -0.5f, -0.5f),
        new Vector3( 0.5f, -0.5f,  0.5f),
        new Vector3( 0.5f,  0.5f,  0.5f),
        new Vector3( 0.5f,  0.5f, -0.5f)
    }
};

private static readonly Vector3[][] billboardVertices = new Vector3[][]
{
    new Vector3[]
    {
        new Vector3(-0.5f, -0.5f, -0.5f),
        new Vector3( 0.5f, -0.5f,  0.5f),
        new Vector3( 0.5f,  0.5f,  0.5f),
        new Vector3(-0.5f,  0.5f, -0.5f)
    },
    new Vector3[]
    {
        new Vector3(-0.5f, -0.5f,  0.5f),
        new Vector3( 0.5f, -0.5f, -0.5f),
        new Vector3( 0.5f,  0.5f, -0.5f),
        new Vector3(-0.5f,  0.5f,  0.5f)
    }
};

void Start()
{
    InitializeBlockConfigs();
    CreateTextureAtlas();
    StartCoroutine(FetchBlocks());
}

private void InitializeBlockConfigs()
{
    blockConfigMap.Clear();
    foreach (var config in blockConfigs)
    {
        config.SetDefaults(config.blockName);
        blockConfigMap[config.blockName] = config;
    }
}

private void CreateTextureAtlas()
{
    string[] textureFiles = Directory.GetFiles(texturePath, "*.png");
    List<Texture2D> texturesList = new List<Texture2D>();
    Dictionary<string, Texture2D> maskTextures = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase);

    string maskPath = Path.Combine(texturePath, "Masks");
    if (Directory.Exists(maskPath))
    {
        foreach (string maskFile in Directory.GetFiles(maskPath, "*.png"))
        {
            string maskName = Path.GetFileNameWithoutExtension(maskFile);
            byte[] maskData = File.ReadAllBytes(maskFile);
            Texture2D maskTexture = new Texture2D(2, 2, TextureFormat.RGBA32, false);
            maskTexture.LoadImage(maskData);
            maskTextures[maskName] = maskTexture;
            Debug.Log($"Loaded mask texture: {maskName}");
        }
    }

    // Process default texture
    string defaultTexturePath = Path.Combine(texturePath, defaultTextureName + ".png");
    if (File.Exists(defaultTexturePath))
    {
        byte[] defaultTextureData = File.ReadAllBytes(defaultTexturePath);
        Texture2D defaultTexture = new Texture2D(2, 2, TextureFormat.RGBA32, false);
        defaultTexture.filterMode = FilterMode.Point;
        defaultTexture.LoadImage(defaultTextureData);
        texturesList.Add(defaultTexture);
        blockNameToTextureIndex[defaultTextureName] = 0;
        defaultTextureIndex = 0;
        Debug.Log($"Loaded default texture: {defaultTextureName} at index {defaultTextureIndex}");
    }
    else
    {
        Debug.LogError($"Default texture {defaultTexturePath} not found! Creating fallback texture.");
        Texture2D fallbackTexture = CreateFallbackTexture();
        texturesList.Add(fallbackTexture);
        defaultTextureIndex = 0;
    }

    // Process all other textures
    foreach (string textureFile in textureFiles)
    {
        string fileName = Path.GetFileNameWithoutExtension(textureFile);
        if (fileName.Equals(defaultTextureName, StringComparison.OrdinalIgnoreCase))
            continue; // Already processed default texture
        byte[] fileData = File.ReadAllBytes(textureFile);
        Texture2D texture = new Texture2D(2, 2, TextureFormat.RGBA32, false);
        texture.filterMode = FilterMode.Point;
        texture.LoadImage(fileData);

        foreach (var config in blockTintConfigs)
        {
            if (fileName.Equals(config.blockName, StringComparison.OrdinalIgnoreCase))
            {
                Color[] pixels = texture.GetPixels();
                Color[] maskPixels = null;
                if (!string.IsNullOrEmpty(config.maskName) &&
                    maskTextures.TryGetValue(config.maskName, out Texture2D maskTexture))
                {
                    if (maskTexture.width == texture.width && maskTexture.height == texture.height)
                    {
                        maskPixels = maskTexture.GetPixels();
                    }
                    else
                    {
                        Debug.LogWarning($"Mask texture {config.maskName} dimensions don't match block texture {fileName}");
                    }
                }

                for (int i = 0; i < pixels.Length; i++)
                {
                    if (maskPixels != null)
                    {
                        float maskIntensity = maskPixels[i].grayscale;
                        pixels[i].r = Mathf.Lerp(pixels[i].r, pixels[i].r * config.tintColor.r, maskIntensity);
                        pixels[i].g = Mathf.Lerp(pixels[i].g, pixels[i].g * config.tintColor.g, maskIntensity);
                        pixels[i].b = Mathf.Lerp(pixels[i].b, pixels[i].b * config.tintColor.b, maskIntensity);
                    }
                    else
                    {
                        pixels[i].r *= config.tintColor.r;
                        pixels[i].g *= config.tintColor.g;
                        pixels[i].b *= config.tintColor.b;
                    }
                    pixels[i].r = Mathf.Clamp01(pixels[i].r);
                    pixels[i].g = Mathf.Clamp01(pixels[i].g);
                    pixels[i].b = Mathf.Clamp01(pixels[i].b);
                }

                texture.SetPixels(pixels);
                texture.Apply();
                break;
            }
        }

        int textureIndex = texturesList.Count;
        texturesList.Add(texture);
        blockNameToTextureIndex[fileName] = textureIndex;
        Debug.Log($"Mapped texture {fileName} to index {textureIndex}");
    }

    textureAtlas = new Texture2D(2048, 2048, TextureFormat.RGBA32, false);
    textureAtlas.filterMode = FilterMode.Point;
    atlasRects = textureAtlas.PackTextures(texturesList.ToArray(), 0, 2048);
    textureAtlas.Apply(false, true);
    blockMaterial.mainTexture = textureAtlas;
    blockMaterial.mainTexture.filterMode = FilterMode.Point;
    foreach (var maskTexture in maskTextures.Values)
    {
        UnityEngine.Object.Destroy(maskTexture);
    }
}

private Texture2D CreateFallbackTexture()
{
    Texture2D fallback = new Texture2D(16, 16, TextureFormat.RGBA32, false);
    fallback.filterMode = FilterMode.Point;

    Color pink = new Color(1f, 0f, 1f, 1f);
    Color black = Color.black;

    for (int y = 0; y < 16; y++)
    {
        for (int x = 0; x < 16; x++)
        {
            Color color = ((x + y) % 2 == 0) ? pink : black;
            fallback.SetPixel(x, y, color);
        }
    }

    fallback.Apply();
    return fallback;
}

private int GetTextureIndexForTextureName(string textureName)
{
    if (blockNameToTextureIndex.TryGetValue(textureName, out int textureIndex))
    {
        return textureIndex;
    }

    Debug.LogWarning($"No texture found for name: {textureName}. Using default texture.");
    return defaultTextureIndex;
}

private Vector2[] GetUVsForTexture(string textureName)
{
    int textureIndex = GetTextureIndexForTextureName(textureName);

    if (textureIndex >= atlasRects.Length || textureIndex < 0)
    {
        Debug.LogError($"Invalid texture index: {textureIndex} for texture: {textureName}");
        textureIndex = defaultTextureIndex;
    }

    if (!uvCache.TryGetValue(textureIndex, out Vector2[] uvs))
    {
        Rect uvRect = atlasRects[textureIndex];
        uvs = new Vector2[]
        {
            new Vector2(uvRect.x, uvRect.y),
            new Vector2(uvRect.x + uvRect.width, uvRect.y),
            new Vector2(uvRect.x + uvRect.width, uvRect.y + uvRect.height),
            new Vector2(uvRect.x, uvRect.y + uvRect.height)
        };
        uvCache[textureIndex] = uvs;
    }
    return uvs;
}

private IEnumerator FetchBlocks()
{
    using (UnityWebRequest webRequest = UnityWebRequest.Get(serverUrl))
    {
        yield return webRequest.SendWebRequest();

        if (webRequest.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError("Error fetching block data: " + webRequest.error);
        }
        else
        {
            string jsonResponse = webRequest.downloadHandler.text;
            blockDataList = JsonConvert.DeserializeObject<List<BlockData>>(jsonResponse);

            foreach (var block in blockDataList)
            {
                AddBlockFaces(block);
            }

            CreateMesh();
        }
    }
}

private void AddBlockFaces(BlockData block)
{
    Vector3 blockPosition = new Vector3(block.x, block.y, block.z);

    if (!blockConfigMap.TryGetValue(block.block_name, out BlockTextureConfig config))
    {
        config = new BlockTextureConfig { blockName = block.block_name };
        config.SetDefaults(block.block_name);
    }

    Dictionary<string, Mesh> customMeshes = new Dictionary<string, Mesh>
    {
        { "_slab", slabMesh },
        { "_fence", fenceMesh },
        { "_stairs", stairMesh }
    };
    string replace = null;
    string add = null;

    Mesh selectedMesh = config.customMesh;

    if (selectedMesh == null)
    {
        foreach (var kvp in customMeshes)
        {
            if (config.blockName.Contains(kvp.Key))
            {
                selectedMesh = kvp.Value;
                replace = kvp.Key;

                if (woodTypes.Any(config.front.Contains))
                {
                    add = "_planks";
                }
                break;
            }
        }
    }

    if (selectedMesh != null)
    {
        AddCustomMeshToChunk(blockPosition, selectedMesh, config.front, replace, add);
    }
    else if (config.isBillboard)
    {
        AddBillboardFacesToChunk(blockPosition, config);
    }
    else
    {
        AddDefaultCubeFacesToChunk(blockPosition, config);
    }
}

private void AddCustomMeshToChunk(
    Vector3 blockPosition,
    Mesh customMesh,
    string textureName,
    string replace,
    string add
)
{
    if (replace != null)
    {
        textureName = textureName.Replace(replace, "") + add;
    }

    MeshChunk chunk = GetCurrentChunk();
    Vector2[] textureUVs = GetUVsForTexture(textureName);
    int vertCount = chunk.vertices.Count;

    Vector3[] vertices = customMesh.vertices;
    int[] triangles = customMesh.triangles;
    int vertexCount = vertices.Length;

    for (int i = 0; i < vertexCount; i++)
    {
        chunk.vertices.Add(vertices[i] + blockPosition);
        chunk.uvs.Add(textureUVs[i % 4]);
    }

    for (int i = 0; i < triangles.Length; i++)
    {
        chunk.triangles.Add(vertCount + triangles[i]);
    }
}

private MeshChunk GetCurrentChunk()
{
    if (meshChunks.Count == 0 || meshChunks[meshChunks.Count - 1].isFull)
    {
        meshChunks.Add(new MeshChunk());
    }
    return meshChunks[meshChunks.Count - 1];
}

private void AddBillboardFacesToChunk(Vector3 blockPosition, BlockTextureConfig config)
{
    Vector2[] textureUVs = GetUVsForTexture(config.front);

    for (int planeIndex = 0; planeIndex < 2; planeIndex++)
    {
        MeshChunk chunk = GetCurrentChunk();
        int vertCount = chunk.vertices.Count;

        for (int i = 0; i < 4; i++)
        {
            chunk.vertices.Add(billboardVertices[planeIndex][i] + blockPosition);
            chunk.uvs.Add(textureUVs[i]);
        }

        chunk.triangles.Add(vertCount + 0);
        chunk.triangles.Add(vertCount + 2);
        chunk.triangles.Add(vertCount + 1);
        chunk.triangles.Add(vertCount + 0);
        chunk.triangles.Add(vertCount + 3);
        chunk.triangles.Add(vertCount + 2);

        chunk = GetCurrentChunk();
        vertCount = chunk.vertices.Count;

        for (int i = 0; i < 4; i++)
        {
            chunk.vertices.Add(billboardVertices[planeIndex][i] + blockPosition);
            chunk.uvs.Add(textureUVs[i]);
        }

        chunk.triangles.Add(vertCount + 0);
        chunk.triangles.Add(vertCount + 1);
        chunk.triangles.Add(vertCount + 2);
        chunk.triangles.Add(vertCount + 0);
        chunk.triangles.Add(vertCount + 2);
        chunk.triangles.Add(vertCount + 3);
    }
}

private void AddDefaultCubeFacesToChunk(Vector3 blockPosition, BlockTextureConfig config)
{
    string[] faceTextures = new string[]
    {
        config.front,
        config.back,
        config.top,
        config.bottom,
        config.left,
        config.right
    };

    for (int faceIndex = 0; faceIndex < 6; faceIndex++)
    {
        MeshChunk chunk = GetCurrentChunk();
        Vector2[] textureUVs = GetUVsForTexture(faceTextures[faceIndex]);
        int vertCount = chunk.vertices.Count;

        for (int i = 0; i < 4; i++)
        {
            chunk.vertices.Add(faceVertices[faceIndex, i] + blockPosition);
            chunk.uvs.Add(textureUVs[i]);
        }

        chunk.triangles.Add(vertCount + 0);
        chunk.triangles.Add(vertCount + 2);
        chunk.triangles.Add(vertCount + 1);
        chunk.triangles.Add(vertCount + 0);
        chunk.triangles.Add(vertCount + 3);
        chunk.triangles.Add(vertCount + 2);
    }
}

private void CreateMesh()
{
    GameObject chunksParent = new GameObject("ChunkedMeshes");
    chunksParent.transform.position = Vector3.zero;

    for (int i = 0; i < meshChunks.Count; i++)
    {
        MeshChunk chunk = meshChunks[i];
        GameObject chunkObject = new GameObject($"MeshChunk_{i}");
        chunkObject.transform.parent = chunksParent.transform;
        chunkObject.transform.localPosition = Vector3.zero;

        MeshFilter meshFilter = chunkObject.AddComponent<MeshFilter>();
        MeshRenderer meshRenderer = chunkObject.AddComponent<MeshRenderer>();
        Mesh mesh = new Mesh();
        mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

        mesh.SetVertices(chunk.vertices);
        mesh.SetTriangles(chunk.triangles, 0);
        mesh.SetUVs(0, chunk.uvs);

        mesh.RecalculateNormals();

        meshFilter.mesh = mesh;
        meshRenderer.material = blockMaterial;

        chunkObject.AddComponent<MeshCollider>().sharedMesh = mesh;
    }

    Debug.Log($"Created {meshChunks.Count} mesh chunks");
}
}