public void PlaceAndRemoveDynamicLightNextToEachOther()
        {
            ChunkNeighbourhood neighbourhood = new ChunkNeighbourhood(Vector3Int.zero, GetMockChunkData);

            Vector3Int testPos = new Vector3Int(5, 0, 0);

            FakeGenerationOfNeighbours(neighbourhood.center.ChunkID);

            //place two lights
            lightManager.UpdateLightOnVoxelSet(neighbourhood, Vector3Int.zero, lampId, (VoxelTypeID)VoxelTypeID.AIR_ID);
            lightManager.UpdateLightOnVoxelSet(neighbourhood, testPos, lampId, (VoxelTypeID)VoxelTypeID.AIR_ID);

            //PrintSlice(neighbourhood,0);

            //remove the second one
            lightManager.UpdateLightOnVoxelSet(neighbourhood, testPos, (VoxelTypeID)VoxelTypeID.AIR_ID, lampId);

            //PrintSlice(neighbourhood,0);

            //The remaining light should be that of the first light only
            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    for (int x = -maxIntensity; x <= maxIntensity; x++)
                    {
                        var pos        = new Vector3Int(x, y, z);
                        var expectedLv = math.max(maxIntensity - pos.ManhattanMagnitude(), 0);
                        Assert.AreEqual(expectedLv, neighbourhood.GetLight(x, y, z).Dynamic,
                                        $"Light value not as expected for position {x},{y},{z}");
                    }
                }
            }
        }
        public void OnChunkGeneratedWithLightWithNeighbourFullyGenerated(int hm)
        {
            var vp            = Vector3Int.zero;
            var lampPos       = vp;
            var neighbourhood = neighbourhoodFor(ref vp);

            //act as if this voxel was generated as part of the chunk
            neighbourhood.SetVoxel(vp.x, vp.y, vp.z, lampId);

            heightMapYValue = hm;

            //generate another chunk next to this one, the light should spill in from the zero chunk
            var tstChunkId = new Vector3Int(-1, 0, 0);

            RunLightingGeneration(tstChunkId);
            lightManager.Update();

            //run the generation action for the zero chunk
            RunLightingGeneration(neighbourhood.center.ChunkID);
            lightManager.Update();

            //PrintSlice(neighbourhood, 0);

            ///Should have propagated the lamp light only within the center chunk
            ///and the newly added chunk
            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    for (int x = -maxIntensity; x <= maxIntensity; x++)
                    {
                        var pos        = new Vector3Int(x, y, z);
                        var expectedLv = new LightValue()
                        {
                            Sun = (hm < 0) ? maxIntensity : 0
                        };
                        expectedLv.Dynamic = math.max(maxIntensity - pos.ManhattanMagnitude(), 0);

                        if (!insideChunkId(pos, Vector3Int.zero) && !insideChunkId(pos, tstChunkId))
                        {
                            expectedLv.Dynamic = 0;
                            expectedLv.Sun     = 0;
                        }

                        if (pos.Equals(lampPos))
                        {//This is where the lamp is, lamps are opaque to sunlight
                            expectedLv.Sun = 0;
                        }

                        Assert.AreEqual(expectedLv, neighbourhood.GetLight(x, y, z),
                                        $"Light value not as expected for position {x},{y},{z}");
                    }
                }
            }
        }
        public void PlaceBarrierThenLamp()
        {
            ChunkNeighbourhood neighbourhood = new ChunkNeighbourhood(Vector3Int.zero, GetMockChunkData);

            FakeGenerationOfNeighbours(neighbourhood.center.ChunkID);

            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    setVoxel(new Vector3Int(-1, y, z), blockerId);
                }
            }

            //Create lamp
            setVoxel(Vector3Int.zero, lampId);

            //PrintSlice(neighbourhood, 0);

            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    for (int x = -maxIntensity; x <= maxIntensity; x++)
                    {
                        var pos        = new Vector3Int(x, y, z);
                        var expectedLv = math.max(maxIntensity - pos.ManhattanMagnitude(), 0);

                        if (x <= -1)
                        {
                            expectedLv = 0;
                        }

                        Assert.AreEqual(expectedLv, neighbourhood.GetLight(x, y, z).Dynamic,
                                        $"Light value not as expected for position {x},{y},{z}");
                    }
                }
            }
        }
        public void PlaceLampNoBarrier()
        {
            ChunkNeighbourhood neighbourhood = new ChunkNeighbourhood(Vector3Int.zero, GetMockChunkData);

            FakeGenerationOfNeighbours(neighbourhood.center.ChunkID);

            lightManager.UpdateLightOnVoxelSet(neighbourhood, Vector3Int.zero, lampId, (VoxelTypeID)VoxelTypeID.AIR_ID);

            //PrintSlice(neighbourhood, 0);

            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    for (int x = -maxIntensity; x <= maxIntensity; x++)
                    {
                        var pos        = new Vector3Int(x, y, z);
                        var expectedLv = math.max(maxIntensity - pos.ManhattanMagnitude(), 0);
                        Assert.AreEqual(expectedLv, neighbourhood.GetLight(x, y, z).Dynamic,
                                        $"Light value not as expected for position {x},{y},{z}");
                    }
                }
            }
        }
        public void PlaceBarrierThenLampThenRemoveBarrier()
        {
            ChunkNeighbourhood neighbourhood = new ChunkNeighbourhood(Vector3Int.zero, GetMockChunkData);

            FakeGenerationOfNeighbours(neighbourhood.center.ChunkID);

            //Create barrier before lamp
            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    setVoxel(new Vector3Int(-1, y, z), blockerId);
                }
            }

            //create lamp
            lightManager.UpdateLightOnVoxelSet(neighbourhood, Vector3Int.zero, lampId, (VoxelTypeID)VoxelTypeID.AIR_ID);

            //Assert light blocked correctly
            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    for (int x = -maxIntensity; x <= maxIntensity; x++)
                    {
                        var pos        = new Vector3Int(x, y, z);
                        var expectedLv = math.max(maxIntensity - pos.ManhattanMagnitude(), 0);

                        if (x <= -1)
                        {
                            expectedLv = 0;
                        }

                        Assert.AreEqual(expectedLv, neighbourhood.GetLight(x, y, z).Dynamic,
                                        $"Light value not as expected for position {x},{y},{z}");
                    }
                }
            }

            //Remove barrier
            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    setVoxel(new Vector3Int(-1, y, z), (VoxelTypeID)VoxelTypeID.AIR_ID);
                }
            }

            //PrintSlice(neighbourhood, 0);

            //Assert light no longer blocked
            for (int z = -maxIntensity; z <= maxIntensity; z++)
            {
                for (int y = -maxIntensity; y <= maxIntensity; y++)
                {
                    for (int x = -maxIntensity; x <= maxIntensity; x++)
                    {
                        var pos        = new Vector3Int(x, y, z);
                        var expectedLv = math.max(maxIntensity - pos.ManhattanMagnitude(), 0);

                        Assert.AreEqual(expectedLv, neighbourhood.GetLight(x, y, z).Dynamic,
                                        $"Light value not as expected for position {x},{y},{z}");
                    }
                }
            }
        }