Exemplo n.º 1
0
        private static void InvalidateVoxel(
            VoxelChunk Chunk,
            GlobalVoxelCoordinate Coordinate,
            int Y)
        {
            Chunk.InvalidateSlice(Y);

            var localCoordinate = Coordinate.GetLocalVoxelCoordinate();

            // Invalidate slice cache for neighbor chunks.
            if (localCoordinate.X == 0)
            {
                InvalidateNeighborSlice(Chunk.Manager.ChunkData, Chunk.ID, new Point3(-1, 0, 0), Y);
                if (localCoordinate.Z == 0)
                {
                    InvalidateNeighborSlice(Chunk.Manager.ChunkData, Chunk.ID, new Point3(-1, 0, -1), Y);
                }
                if (localCoordinate.Z == VoxelConstants.ChunkSizeZ - 1)
                {
                    InvalidateNeighborSlice(Chunk.Manager.ChunkData, Chunk.ID, new Point3(-1, 0, 1), Y);
                }
            }

            if (localCoordinate.X == VoxelConstants.ChunkSizeX - 1)
            {
                InvalidateNeighborSlice(Chunk.Manager.ChunkData, Chunk.ID, new Point3(1, 0, 0), Y);
                if (localCoordinate.Z == 0)
                {
                    InvalidateNeighborSlice(Chunk.Manager.ChunkData, Chunk.ID, new Point3(1, 0, -1), Y);
                }
                if (localCoordinate.Z == VoxelConstants.ChunkSizeZ - 1)
                {
                    InvalidateNeighborSlice(Chunk.Manager.ChunkData, Chunk.ID, new Point3(1, 0, 1), Y);
                }
            }

            if (localCoordinate.Z == 0)
            {
                InvalidateNeighborSlice(Chunk.Manager.ChunkData, Chunk.ID, new Point3(0, 0, -1), Y);
            }

            if (localCoordinate.Z == VoxelConstants.ChunkSizeZ - 1)
            {
                InvalidateNeighborSlice(Chunk.Manager.ChunkData, Chunk.ID, new Point3(0, 0, 1), Y);
            }
        }
Exemplo n.º 2
0
        private void OnTypeSet(VoxelType NewType)
        {
            // Changing a voxel is actually a relatively rare event, so we can afford to do a bit of
            // bookkeeping here.

            var previous       = _cache_Chunk.Data.Types[_cache_Index];
            var blockDestroyed = false;

            // Change actual data
            _cache_Chunk.Data.Types[_cache_Index]  = (byte)NewType.ID;
            _cache_Chunk.Data.Health[_cache_Index] = (byte)NewType.StartingHealth;

            // Changing the voxel type clears grass.
            _cache_Chunk.Data.GrassType[_cache_Index] = 0;

            // Did we go from empty to filled or vice versa? Update filled counter.
            if (previous == 0 && NewType.ID != 0)
            {
                _cache_Chunk.Data.VoxelsPresentInSlice[Coordinate.Y] += 1;
            }
            else if (previous != 0 && NewType.ID == 0)
            {
                blockDestroyed = true;
                _cache_Chunk.Data.VoxelsPresentInSlice[Coordinate.Y] -= 1;
            }

            if (Coordinate.Y < VoxelConstants.ChunkSizeY - 1)
            {
                InvalidateVoxel(_cache_Chunk, Coordinate, Coordinate.Y + 1);
            }
            InvalidateVoxel(_cache_Chunk, Coordinate, Coordinate.Y);

            // Propogate sunlight (or lack thereof) downwards.
            if (Coordinate.Y > 0)
            {
                var localCoordinate = Coordinate.GetLocalVoxelCoordinate();
                var Y        = localCoordinate.Y - 1;
                var sunColor = (NewType.ID == 0 || NewType.IsTransparent) ? this.SunColor : 0;
                var below    = VoxelHandle.InvalidHandle;

                while (Y >= 0)
                {
                    below = new VoxelHandle(Chunk, new LocalVoxelCoordinate(localCoordinate.X, Y,
                                                                            localCoordinate.Z));
                    below.SunColor = sunColor;
                    InvalidateVoxel(Chunk, new GlobalVoxelCoordinate(Coordinate.X, Y, Coordinate.Z), Y);
                    if (!below.IsEmpty && !below.Type.IsTransparent)
                    {
                        break;
                    }
                    Y -= 1;
                }
            }

            if (blockDestroyed)
            {
                // Invoke old voxel listener.
                _cache_Chunk.NotifyDestroyed(Coordinate.GetLocalVoxelCoordinate());

                // Reveal!
                VoxelHelpers.RadiusReveal(_cache_Chunk.Manager.ChunkData, this, 10);
            }

            // Invoke new voxel listener.
            _cache_Chunk.Manager.NotifyChangedVoxel(new VoxelChangeEvent
            {
                Type              = VoxelChangeEventType.VoxelTypeChanged,
                Voxel             = this,
                OriginalVoxelType = previous,
                NewVoxelType      = NewType.ID
            });
        }