private static void UpdateVoxelRamps(ChunkManager Chunks, VoxelHandle V)
        {
            if (!V.IsValid)
            {
                return;
            }

            if (V.IsEmpty || !V.IsVisible || V.Type == null || !V.Type.CanRamp)
            {
                V.RampType = RampType.None;
                return;
            }

            var vAbove = VoxelHelpers.GetVoxelAbove(V);

            if (vAbove.IsValid && !vAbove.IsEmpty)
            {
                V.RampType = RampType.None;
                return;
            }

            var compositeRamp = RampType.None;

            foreach (var vertex in TopVerticies)
            {
                // If there are no empty neighbors, no slope.
                if (!VoxelHelpers.EnumerateVertexNeighbors2D(V.Coordinate, vertex)
                    .Any(n =>
                {
                    var handle = Chunks.CreateVoxelHandle(n);
                    return(!handle.IsValid || handle.IsEmpty);
                }))
                {
                    continue;
                }

                switch (vertex)
                {
                case VoxelVertex.FrontTopLeft:
                    compositeRamp |= RampType.TopFrontLeft;
                    break;

                case VoxelVertex.FrontTopRight:
                    compositeRamp |= RampType.TopFrontRight;
                    break;

                case VoxelVertex.BackTopLeft:
                    compositeRamp |= RampType.TopBackLeft;
                    break;

                case VoxelVertex.BackTopRight:
                    compositeRamp |= RampType.TopBackRight;
                    break;
                }
            }

            V.RampType = compositeRamp;
        }
Exemple #2
0
        public static float GetTotalWaterHeightCells(ChunkManager ChunkManager, VoxelHandle vox)
        {
            float tot = 0;

            var localVoxelCoordinate = vox.Coordinate.GetLocalVoxelCoordinate();

            for (var y = vox.Coordinate.Y; y < ChunkManager.World.WorldSizeInVoxels.Y; y++)
            {
                var v = ChunkManager.CreateVoxelHandle(new GlobalVoxelCoordinate(vox.Coordinate.X, y, vox.Coordinate.Z));
                tot += v.LiquidLevel / (float)WaterManager.maxWaterLevel;
                if (y > vox.Coordinate.Y && v.LiquidLevel == 0)
                {
                    return(tot);
                }
            }

            return(tot);
        }
        private static VertexColorInfo CalculateVertexLight(VoxelHandle Vox, VoxelVertex Vertex, ChunkManager chunks)
        {
            var neighborsEmpty   = 0;
            var neighborsChecked = 0;

            var color = new VertexColorInfo();

            color.DynamicColor = 0;
            color.SunColor     = 0;

            foreach (var c in VoxelHelpers.EnumerateVertexNeighbors(Vox.Coordinate, Vertex))
            {
                var v = chunks.CreateVoxelHandle(c);
                if (!v.IsValid)
                {
                    continue;
                }

                color.SunColor += v.Sunlight ? 255 : 0;

                if (!v.IsEmpty || !v.IsExplored)
                {
                    if (v.Type.EmitsLight)
                    {
                        color.DynamicColor = 255;
                    }

                    neighborsEmpty   += 1;
                    neighborsChecked += 1;
                }
                else
                {
                    neighborsChecked += 1;
                }
            }

            var boost         = GetAmbienceBoost(Vertex);
            var proportionHit = (float)neighborsEmpty / (float)neighborsChecked;

            color.AmbientColor = (int)Math.Min((1.0f - proportionHit) * 255.0f, 255);
            color.SunColor     = (int)Math.Min((float)color.SunColor / (float)neighborsChecked + boost * 255.0f, 255);

            return(color);
        }
Exemple #4
0
        private void DiscreteUpdate(ChunkManager ChunkManager, VoxelChunk chunk)
        {
            for (var y = 0; y < VoxelConstants.ChunkSizeY; ++y)
            {
                // Apply 'liquid present' tracking in voxel data to skip entire slices.
                if (chunk.Data.LiquidPresent[y] == 0)
                {
                    continue;
                }

                var layerOrder = SlicePermutations[MathFunctions.RandInt(0, SlicePermutations.Length)];

                for (var i = 0; i < layerOrder.Length; ++i)
                {
                    var x            = layerOrder[i] % VoxelConstants.ChunkSizeX;
                    var z            = (layerOrder[i] >> VoxelConstants.XDivShift) % VoxelConstants.ChunkSizeZ;
                    var currentVoxel = VoxelHandle.UnsafeCreateLocalHandle(chunk, new LocalVoxelCoordinate(x, y, z));

                    if (currentVoxel.TypeID != 0)
                    {
                        continue;
                    }

                    if (currentVoxel.LiquidType == LiquidType.None || currentVoxel.LiquidLevel < 1)
                    {
                        continue;
                    }

                    // Evaporate.
                    if (currentVoxel.LiquidLevel <= EvaporationLevel && MathFunctions.RandEvent(0.01f))
                    {
                        if (currentVoxel.LiquidType == LiquidType.Lava)
                        {
                            currentVoxel.Type = Library.GetVoxelType("Stone");
                        }

                        NeedsMinimapUpdate = true;
                        currentVoxel.QuickSetLiquid(LiquidType.None, 0);
                        continue;
                    }

                    var voxBelow = ChunkManager.CreateVoxelHandle(new GlobalVoxelCoordinate(currentVoxel.Coordinate.X, currentVoxel.Coordinate.Y - 1, currentVoxel.Coordinate.Z));

                    if (voxBelow.IsValid && voxBelow.IsEmpty)
                    {
                        // Fall into the voxel below.

                        // Special case: No liquid below, just drop down.
                        if (voxBelow.LiquidType == LiquidType.None)
                        {
                            NeedsMinimapUpdate = true;
                            CreateSplash(currentVoxel.Coordinate.ToVector3(), currentVoxel.LiquidType);
                            voxBelow.QuickSetLiquid(currentVoxel.LiquidType, currentVoxel.LiquidLevel);
                            currentVoxel.QuickSetLiquid(LiquidType.None, 0);
                            continue;
                        }

                        var belowType      = voxBelow.LiquidType;
                        var aboveType      = currentVoxel.LiquidType;
                        var spaceLeftBelow = maxWaterLevel - voxBelow.LiquidLevel;

                        if (spaceLeftBelow >= currentVoxel.LiquidLevel)
                        {
                            NeedsMinimapUpdate = true;
                            CreateSplash(currentVoxel.Coordinate.ToVector3(), aboveType);
                            voxBelow.LiquidLevel += currentVoxel.LiquidLevel;
                            currentVoxel.QuickSetLiquid(LiquidType.None, 0);
                            HandleLiquidInteraction(voxBelow, aboveType, belowType);
                            continue;
                        }

                        if (spaceLeftBelow > 0)
                        {
                            NeedsMinimapUpdate = true;
                            CreateSplash(currentVoxel.Coordinate.ToVector3(), aboveType);
                            currentVoxel.LiquidLevel = (byte)(currentVoxel.LiquidLevel - maxWaterLevel + voxBelow.LiquidLevel);
                            voxBelow.LiquidLevel     = maxWaterLevel;
                            HandleLiquidInteraction(voxBelow, aboveType, belowType);
                            continue;
                        }
                    }
                    else if (voxBelow.IsValid && currentVoxel.LiquidType == LiquidType.Lava && !voxBelow.IsEmpty && voxBelow.GrassType > 0)
                    {
                        voxBelow.GrassType = 0;
                    }

                    if (currentVoxel.LiquidLevel <= 1)
                    {
                        continue;
                    }

                    // Nothing left to do but spread.

                    RollArray(NeighborPermutations[MathFunctions.RandInt(0, NeighborPermutations.Length)], NeighborScratch, MathFunctions.RandInt(0, 4));

                    for (var n = 0; n < NeighborScratch.Length; ++n)
                    {
                        var neighborOffset = VoxelHelpers.ManhattanNeighbors2D[NeighborScratch[n]];
                        var neighborVoxel  = new VoxelHandle(Chunks, currentVoxel.Coordinate + neighborOffset);

                        if (neighborVoxel.IsValid && neighborVoxel.IsEmpty)
                        {
                            if (neighborVoxel.LiquidLevel < currentVoxel.LiquidLevel)
                            {
                                NeedsMinimapUpdate = true;
                                var amountToMove = (int)(currentVoxel.LiquidLevel * GetSpreadRate(currentVoxel.LiquidType));
                                if (neighborVoxel.LiquidLevel + amountToMove > maxWaterLevel)
                                {
                                    amountToMove = maxWaterLevel - neighborVoxel.LiquidLevel;
                                }

                                if (amountToMove > 2)
                                {
                                    CreateSplash(neighborVoxel.Coordinate.ToVector3(), currentVoxel.LiquidType);
                                }

                                var newWater = currentVoxel.LiquidLevel - amountToMove;

                                var sourceType = currentVoxel.LiquidType;
                                var destType   = neighborVoxel.LiquidType;
                                currentVoxel.QuickSetLiquid(newWater == 0 ? LiquidType.None : sourceType, (byte)newWater);
                                neighborVoxel.QuickSetLiquid(destType == LiquidType.None ? sourceType : destType, (byte)(neighborVoxel.LiquidLevel + amountToMove));
                                HandleLiquidInteraction(neighborVoxel, sourceType, destType);
                                break;
                            }
                        }
                    }
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Snaps the supplied coordinate into valid world space. Returns nearest valid voxel to the point.
        /// </summary>
        /// <param name="chunks"></param>
        /// <param name="pos"></param>
        /// <returns></returns>
        public static VoxelHandle FindValidVoxelNear(ChunkManager chunks, Microsoft.Xna.Framework.Vector3 pos)
        {
            var clampedPos = MathFunctions.Clamp(pos, chunks.Bounds) + Microsoft.Xna.Framework.Vector3.Down * 0.05f;

            return(chunks.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(clampedPos)));
        }