Exemplo n.º 1
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
            });
        }