public void Execute()
        {
            NativeArray <float3> verts     = new NativeArray <float3>(4, Allocator.Temp);
            NativeArray <float2> uv        = new NativeArray <float2>(4, Allocator.Temp);
            NativeArray <int>    triangles = new NativeArray <int>(6, Allocator.Temp);

            NativeArray <bool> drawFace = new NativeArray <bool>(6, Allocator.Temp);
            NativeArray <bool> flipFace = new NativeArray <bool>(6, Allocator.Temp);

            NativeArray <short> nearbyLiquidSourceDistance = new NativeArray <short>(4, Allocator.Temp);

            for (int x = 1; x < WorldSettings.ChunkSizeXZ + 1; x++)
            {
                for (int z = 1; z < WorldSettings.ChunkSizeXZ + 1; z++)
                {
                    for (int y = 0; y < WorldSettings.ChunkSizeY; y++)
                    {
                        int       index     = Utils.BlockPosition3DtoIndex(x, y, z);
                        BlockType blockType = blocks[index];

                        if (blockType == BlockType.AIR)
                        {
                            continue;
                        }

                        int3 blockPos = new int3(x - 1, y, z - 1);
                        int  numFaces = 0;

                        BlockStructure block = WorldData.GetBlockData(blockType);

                        short param = 0;

                        // assign default values
                        ref var verticles = ref blockVerticles;
                        ref var uvs       = ref blockUVs;
                        ref var tris      = ref blockTriangles;

                        // check for visible faces
                        switch (block.shape)
                        {
                        case BlockShape.LIQUID:
                            verticles = ref liquidVerticles;
                            uvs       = ref liquidUVs;
                            tris      = ref liquidTriangles;

                            // set to full by default to not save full blocks in game saves
                            if (!blockParameters.TryGetValue(new BlockParameter(new int3(x, y, z), ParameterType.WATER_SOURCE_DISTANCE), out param))
                            {
                                param = 8;
                            }

                            BlockstateLiquid(drawFace, index, x, y, z);
                            break;

                        case BlockShape.HALF_BLOCK:
                            blockParameters.TryGetValue(new BlockParameter(new int3(x, y, z), ParameterType.ROTATION), out param);

                            BlockstateSolidHalf(drawFace, index, x, y, z, param);
                            break;

                        case BlockShape.GRASS:
                            verticles = ref plantsVerticles;
                            uvs       = ref plantsUVs;
                            tris      = ref plantsTriangles;

                            blockParameters.TryGetValue(new BlockParameter(new int3(x, y, z), ParameterType.BLOCK_TYPE), out param);

                            BlockstateGrass(drawFace, index, x, y, z);
                            break;

                        default:
                            BlockstateSolid(drawFace, index, x, y, z);
                            break;
                        }

                        // draw faces
                        if (block.shape == BlockShape.LIQUID)
                        {
                            short value;
                            for (int i = 0; i < 6; i++)
                            {
                                if (!drawFace[i])
                                {
                                    continue;
                                }

                                // R L F B
                                nearbyLiquidSourceDistance[0] = blockParameters.TryGetValue(new BlockParameter(new int3(x + 1, y, z), ParameterType.WATER_SOURCE_DISTANCE), out value) ? value : (short)0;
                                nearbyLiquidSourceDistance[1] = blockParameters.TryGetValue(new BlockParameter(new int3(x - 1, y, z), ParameterType.WATER_SOURCE_DISTANCE), out value) ? value : (short)0;
                                nearbyLiquidSourceDistance[2] = blockParameters.TryGetValue(new BlockParameter(new int3(x, y, z + 1), ParameterType.WATER_SOURCE_DISTANCE), out value) ? value : (short)0;
                                nearbyLiquidSourceDistance[3] = blockParameters.TryGetValue(new BlockParameter(new int3(x, y, z - 1), ParameterType.WATER_SOURCE_DISTANCE), out value) ? value : (short)0;

                                bool reverse = block.GetWaterShape((BlockFace)i, blockPos, verts, uv, param, nearbyLiquidSourceDistance);
                                verticles.AddRange(verts);
                                uvs.AddRange(uv);

                                flipFace[numFaces] = reverse;
                                numFaces++;
                            }
                        }
                        else
                        {
                            for (int i = 0; i < 6; i++)
                            {
                                if (!drawFace[i])
                                {
                                    continue;
                                }
                                bool reverse = block.GetBlockShape((BlockFace)i, blockPos, verts, uv, param);
                                verticles.AddRange(verts);
                                uvs.AddRange(uv);

                                flipFace[numFaces] = reverse;
                                numFaces++;
                            }
                        }

                        // triangles
                        int tl = verticles.Length - 4 * numFaces;
                        for (int i = 0; i < numFaces; i++)
                        {
                            if (flipFace[i])
                            {
                                triangles[5] = tl + i * 4;
                                triangles[4] = tl + i * 4 + 1;
                                triangles[3] = tl + i * 4 + 2;
                                triangles[2] = tl + i * 4;
                                triangles[1] = tl + i * 4 + 2;
                                triangles[0] = tl + i * 4 + 3;
                            }
                            else
                            {
                                triangles[0] = tl + i * 4;
                                triangles[1] = tl + i * 4 + 1;
                                triangles[2] = tl + i * 4 + 2;
                                triangles[3] = tl + i * 4;
                                triangles[4] = tl + i * 4 + 2;
                                triangles[5] = tl + i * 4 + 3;
                            }

                            tris.AddRange(triangles);
                        }
                    }