void AddBeaches([NotNull] Map map) { if (map == null) { throw new ArgumentNullException("map"); } int beachExtentSqr = (args.BeachExtent + 1) * (args.BeachExtent + 1); for (int x = 0; x < map.Width; x++) { for (int y = 0; y < map.Length; y++) { for (int z = args.WaterLevel; z <= args.WaterLevel + args.BeachHeight; z++) { if (map.GetBlock(x, y, z) != bGroundSurface) { continue; } bool found = false; for (int dx = -args.BeachExtent; !found && dx <= args.BeachExtent; dx++) { for (int dy = -args.BeachExtent; !found && dy <= args.BeachExtent; dy++) { for (int dz = -args.BeachHeight; dz <= 0; dz++) { if (dx * dx + dy * dy + dz * dz > beachExtentSqr) { continue; } int xx = x + dx; int yy = y + dy; int zz = z + dz; if (xx < 0 || xx >= map.Width || yy < 0 || yy >= map.Length || zz < 0 || zz >= map.Height) { continue; } Block block = map.GetBlock(xx, yy, zz); if (block == bWater || block == bWaterSurface) { found = true; break; } } } } if (found) { map.SetBlock(x, y, z, bSeaFloor); if (z > 0 && map.GetBlock(x, y, z - 1) == bGround) { map.SetBlock(x, y, z - 1, bSeaFloor); } } } } } }
private static void SetUpRed() { for (int x = 0; x <= _map.Width; x++) { for (int y = 0; y <= 10; y++) { _map.SetBlock(x, y, _ground, Block.Red); _map.SetBlock(x, y, _ground - 1, Block.Black); } } }
void GenerateTrees([NotNull] Map map) { if (map == null) { throw new ArgumentNullException("map"); } int minHeight = args.TreeHeightMin; int maxHeight = args.TreeHeightMax; int minTrunkPadding = args.TreeSpacingMin; int maxTrunkPadding = args.TreeSpacingMax; const int topLayers = 2; const double odds = 0.618; Random rn = new Random(); map.CalculateShadows(); for (int x = 0; x < map.Width; x += rn.Next(minTrunkPadding, maxTrunkPadding + 1)) { for (int y = 0; y < map.Length; y += rn.Next(minTrunkPadding, maxTrunkPadding + 1)) { int nx = x + rn.Next(-(minTrunkPadding / 2), (maxTrunkPadding / 2) + 1); int ny = y + rn.Next(-(minTrunkPadding / 2), (maxTrunkPadding / 2) + 1); if (nx < 0 || nx >= map.Width || ny < 0 || ny >= map.Length) { continue; } int nz = map.Shadows[nx, ny]; if ((map.GetBlock(nx, ny, nz) == bGroundSurface) && slopemap[nx, ny] < .5) { // Pick a random height for the tree between Min and Max, // discarding this tree if it would breach the top of the map int nh; if ((nh = rn.Next(minHeight, maxHeight + 1)) + nz + nh / 2 > map.Height) { continue; } // Generate the trunk of the tree for (int z = 1; z <= nh; z++) { map.SetBlock(nx, ny, nz + z, Block.Log); } for (int i = -1; i < nh / 2; i++) { // Should we draw thin (2x2) or thicker (4x4) foliage int radius = (i >= (nh / 2) - topLayers) ? 1 : 2; // Draw the foliage for (int xoff = -radius; xoff < radius + 1; xoff++) { for (int yoff = -radius; yoff < radius + 1; yoff++) { // Drop random leaves from the edges if (rn.NextDouble() > odds && Math.Abs(xoff) == Math.Abs(yoff) && Math.Abs(xoff) == radius) { continue; } // By default only replace an existing block if its air if (map.GetBlock(nx + xoff, ny + yoff, nz + nh + i) == Block.Air) { map.SetBlock(nx + xoff, ny + yoff, nz + nh + i, Block.Leaves); } } } } } } } }
public Map GenerateMap() { Map map = new Map(null, args.MapWidth, args.MapLength, args.MapHeight, true); // Match water coverage float desiredWaterLevel = .5f; if (args.MatchWaterCoverage) { ReportProgress(2, "Heightmap Processing: Matching water coverage"); desiredWaterLevel = Noise.FindThreshold(heightmap, args.WaterCoverage); } // Calculate above/below water multipliers float aboveWaterMultiplier = 0; if (desiredWaterLevel != 1) { aboveWaterMultiplier = (args.MaxHeight / (1 - desiredWaterLevel)); } // Apply power functions to above/below water parts of the heightmap if (args.BelowFuncExponent != 1 || args.AboveFuncExponent != 1) { ReportProgress(5, "Heightmap Processing: Adjusting slope"); for (int x = heightmap.GetLength(0) - 1; x >= 0; x--) { for (int y = heightmap.GetLength(1) - 1; y >= 0; y--) { if (heightmap[x, y] < desiredWaterLevel) { float normalizedDepth = 1 - heightmap[x, y] / desiredWaterLevel; heightmap[x, y] = desiredWaterLevel - (float)Math.Pow(normalizedDepth, args.BelowFuncExponent) * desiredWaterLevel; } else { float normalizedHeight = (heightmap[x, y] - desiredWaterLevel) / (1 - desiredWaterLevel); heightmap[x, y] = desiredWaterLevel + (float)Math.Pow(normalizedHeight, args.AboveFuncExponent) * (1 - desiredWaterLevel); } } } } // Calculate the slope if (args.CliffSmoothing) { ReportProgress(2, "Heightmap Processing: Smoothing"); slopemap = Noise.CalculateSlope(Noise.GaussianBlur5X5(heightmap)); } else { slopemap = Noise.CalculateSlope(heightmap); } float[,] altmap = null; if (args.MaxHeightVariation != 0 || args.MaxDepthVariation != 0) { ReportProgress(5, "Heightmap Processing: Randomizing"); altmap = new float[map.Width, map.Length]; int blendmapDetailSize = (int)Math.Log(Math.Max(args.MapWidth, args.MapLength), 2) - 2; new Noise(rand.Next(), NoiseInterpolationMode.Cosine).PerlinNoise(altmap, 3, blendmapDetailSize, 0.5f, 0, 0); Noise.Normalize(altmap, -1, 1); } int snowStartThreshold = args.SnowAltitude - args.SnowTransition; int snowThreshold = args.SnowAltitude; ReportProgress(10, "Filling"); for (int x = heightmap.GetLength(0) - 1; x >= 0; x--) { for (int y = heightmap.GetLength(1) - 1; y >= 0; y--) { int level; float slope; if (heightmap[x, y] < desiredWaterLevel) { float depth = args.MaxDepth; if (altmap != null) { depth += altmap[x, y] * args.MaxDepthVariation; } slope = slopemap[x, y] * depth; level = args.WaterLevel - (int)Math.Round(Math.Pow(1 - heightmap[x, y] / desiredWaterLevel, args.BelowFuncExponent) * depth); if (args.AddWater) { if (args.WaterLevel - level > 3) { map.SetBlock(x, y, args.WaterLevel, bDeepWaterSurface); } else { map.SetBlock(x, y, args.WaterLevel, bWaterSurface); } for (int i = args.WaterLevel; i > level; i--) { map.SetBlock(x, y, i, bWater); } for (int i = level; i >= 0; i--) { if (level - i < SeaFloorThickness) { map.SetBlock(x, y, i, bSeaFloor); } else { map.SetBlock(x, y, i, bBedrock); } } } else { if (blendmap != null && blendmap[x, y] > .25 && blendmap[x, y] < .75) { map.SetBlock(x, y, level, bCliff); } else { if (slope < args.CliffThreshold) { map.SetBlock(x, y, level, bGroundSurface); } else { map.SetBlock(x, y, level, bCliff); } } for (int i = level - 1; i >= 0; i--) { if (level - i < groundThickness) { if (blendmap != null && blendmap[x, y] > CliffsideBlockThreshold && blendmap[x, y] < (1 - CliffsideBlockThreshold)) { map.SetBlock(x, y, i, bCliff); } else { if (slope < args.CliffThreshold) { map.SetBlock(x, y, i, bGround); } else { map.SetBlock(x, y, i, bCliff); } } } else { map.SetBlock(x, y, i, bBedrock); } } } } else { float height; if (altmap != null) { height = args.MaxHeight + altmap[x, y] * args.MaxHeightVariation; } else { height = args.MaxHeight; } slope = slopemap[x, y] * height; if (height != 0) { level = args.WaterLevel + (int)Math.Round(Math.Pow(heightmap[x, y] - desiredWaterLevel, args.AboveFuncExponent) * aboveWaterMultiplier / args.MaxHeight * height); } else { level = args.WaterLevel; } bool snow = args.AddSnow && (level > snowThreshold || (level > snowStartThreshold && rand.NextDouble() < (level - snowStartThreshold) / (double)(snowThreshold - snowStartThreshold))); if (blendmap != null && blendmap[x, y] > .25 && blendmap[x, y] < .75) { map.SetBlock(x, y, level, bCliff); } else { if (slope < args.CliffThreshold) { map.SetBlock(x, y, level, (snow ? Block.White : bGroundSurface)); } else { map.SetBlock(x, y, level, bCliff); } } for (int i = level - 1; i >= 0; i--) { if (level - i < groundThickness) { if (blendmap != null && blendmap[x, y] > CliffsideBlockThreshold && blendmap[x, y] < (1 - CliffsideBlockThreshold)) { map.SetBlock(x, y, i, bCliff); } else { if (slope < args.CliffThreshold) { if (snow) { map.SetBlock(x, y, i, Block.White); } else { map.SetBlock(x, y, i, bGround); } } else { map.SetBlock(x, y, i, bCliff); } } } else { map.SetBlock(x, y, i, bBedrock); } } } } } if (args.AddCaves || args.AddOre) { AddCaves(map); } if (args.AddBeaches) { ReportProgress(5, "Processing: Adding beaches"); AddBeaches(map); } if (args.AddTrees) { ReportProgress(5, "Processing: Planting trees"); if (args.AddGiantTrees) { Map outMap = new Map(null, map.Width, map.Length, map.Height, false) { Blocks = (byte[])map.Blocks.Clone() }; var foresterArgs = new ForesterArgs { Map = map, Rand = rand, TreeCount = (int)(map.Width * map.Length * 4 / (1024f * (args.TreeSpacingMax + args.TreeSpacingMin) / 2)), Operation = Forester.ForesterOperation.Add, PlantOn = bGroundSurface }; foresterArgs.BlockPlacing += (sender, e) => outMap.SetBlock(e.Coordinate, e.Block); Forester.Generate(foresterArgs); map = outMap; } GenerateTrees(map); } ReportProgress(0, "Generation complete"); map.Metadata["_Origin", "GeneratorName"] = "fCraft"; map.Metadata["_Origin", "GeneratorVersion"] = Updater.LatestStable.ToString(); map.Metadata["_Origin", "GeneratorParams"] = args.Serialize().ToString(SaveOptions.DisableFormatting); return(map); }