public bool SetTile(int2 worldTilePosition, int id)
    {
        if (!TileUtil.BoundaryCheck(worldTilePosition, mapSize))
        {
            return(false);
        }

        int index = TileUtil.To1DIndex(worldTilePosition, mapSize);

        if (tiles[index] == id)
        {
            return(false);
        }

        int2 chunkPosition = TileUtil.WorldTileToChunk(worldTilePosition, chunkSize);

        if (chunks.TryGetValue(chunkPosition, out TileChunk chunk))
        {
            chunk.SetMeshDirty();
        }
        else
        {
            TileChunk newChunk = GenerateChunk(chunkPosition);
            newChunk.SetMeshDirty();
        }

        if (tileInformations[id].isSolid)
        {
            fluidQueue.Enqueue(new Tuple <int, float>(index, 0.0f));
        }

        LightEmission beforeEmission = tileInformations[tiles[index]].emission;

        tiles[index] = id;

        SetEmission(worldTilePosition, tileInformations[id].emission);
        CheckTileToUpdateLight(worldTilePosition, id, beforeEmission);

        return(true);
    }
        public void Execute(int tileIndex)
        {
            int2 tilePosition = TileUtil.To2DIndex(tileIndex, mapSize);

            if (tiles[tileIndex] != waterID)
            {
                if (isSolid[tiles[tileIndex]])
                {
                    waterDensities[tileIndex] = 0.0f;
                }

                return;
            }

            if (waterDensities[tileIndex] < minDensity)
            {
                waterDensities[tileIndex] = 0;
                return;
            }

            float remainingDensity = waterDensities[tileIndex];

            if (remainingDensity <= 0)
            {
                return;
            }

            waterChunkDirty[TileUtil.To1DIndex(TileUtil.WorldTileToChunk(tilePosition, chunkSize), numChunks)] = true;

            int2 downPosition = tilePosition + TileUtil.Down;
            int  downIndex    = TileUtil.To1DIndex(downPosition, mapSize);

            if (TileUtil.BoundaryCheck(downPosition, mapSize) && !isSolid[tiles[downIndex]])
            {
                float flow = CalculateStableDensity(remainingDensity + waterDensities[downIndex]) - waterDensities[downIndex];
                if (flow > minFlow)
                {
                    flow *= flowSpeed;
                }

                flow = Mathf.Clamp(flow, 0, Mathf.Min(maxFlow, remainingDensity));
                waterDiff[tileIndex] -= flow;
                waterDiff[downIndex] += flow;
                remainingDensity     -= flow;
            }

            if (remainingDensity < minDensity)
            {
                waterDiff[tileIndex] -= remainingDensity;
                return;
            }

            int2 leftPosition = tilePosition + TileUtil.Left;
            int  leftIndex    = TileUtil.To1DIndex(leftPosition, mapSize);

            if (TileUtil.BoundaryCheck(leftIndex, mapSize) && !isSolid[tiles[leftIndex]])
            {
                float flow = (remainingDensity - waterDensities[leftIndex]) / 4.0f;
                if (flow > minFlow)
                {
                    flow *= flowSpeed;
                }

                flow = Mathf.Clamp(flow, 0, Mathf.Min(maxFlow, remainingDensity));
                waterDiff[tileIndex] -= flow;
                waterDiff[leftIndex] += flow;
                remainingDensity     -= flow;
            }

            if (remainingDensity < minDensity)
            {
                waterDiff[tileIndex] -= remainingDensity;
                return;
            }

            int2 rightPosition = tilePosition + TileUtil.Right;
            int  rightIndex    = TileUtil.To1DIndex(rightPosition, mapSize);

            if (TileUtil.BoundaryCheck(rightIndex, mapSize) && !isSolid[tiles[rightIndex]])
            {
                float flow = (remainingDensity - waterDensities[rightIndex]) / 3.0f;
                if (flow > minFlow)
                {
                    flow *= flowSpeed;
                }

                flow = Mathf.Clamp(flow, 0, Mathf.Min(maxFlow, remainingDensity));
                waterDiff[tileIndex]  -= flow;
                waterDiff[rightIndex] += flow;
                remainingDensity      -= flow;
            }

            if (remainingDensity < minDensity)
            {
                waterDiff[tileIndex] -= remainingDensity;
                return;
            }

            int2 upPosition = tilePosition + TileUtil.Up;
            int  upIndex    = TileUtil.To1DIndex(upPosition, mapSize);

            if (TileUtil.BoundaryCheck(upIndex, mapSize) && !isSolid[tiles[upIndex]])
            {
                float flow = remainingDensity - CalculateStableDensity(remainingDensity + waterDensities[upIndex]);
                if (flow > minFlow)
                {
                    flow *= flowSpeed;
                }

                flow = Mathf.Clamp(flow, 0, Mathf.Min(maxFlow, remainingDensity));
                waterDiff[tileIndex] -= flow;
                waterDiff[upIndex]   += flow;
                remainingDensity     -= flow;
            }

            if (remainingDensity < minDensity)
            {
                waterDiff[tileIndex] -= remainingDensity;
            }
        }