public Map GenerateMap() { Map map = new Map(null, args.WidthX, args.WidthY, args.Height, true); // Match water coverage float desiredWaterLevel = .5f; if (args.MatchWaterCoverage) { ReportProgress(2, "Heightmap Processing: Matching water coverage"); desiredWaterLevel = MatchWaterCoverage(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); } int level; float slope; /* draw heightmap visually (DEBUG) * * * float underWaterMultiplier = 0; * if( desiredWaterLevel != 0 ) { * underWaterMultiplier = (float)(args.maxDepth / desiredWaterLevel); * } * * 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 ) { * slope = slopemap[x, y] * args.maxDepth; * level = args.waterLevel - (int)Math.Round( (desiredWaterLevel - heightmap[x, y]) * underWaterMultiplier ); * } else { * slope = slopemap[x, y] * args.maxHeight; * level = args.waterLevel + (int)Math.Round( (heightmap[x, y] - desiredWaterLevel) * aboveWaterMultiplier ); * } * Block block; * if( slope < .12 ) { * block = Block.Green; * } else if( slope < .24 ) { * block = Block.Lime; * } else if( slope < .36 ) { * block = Block.Yellow; * } else if( slope < .48 ) { * block = Block.Orange; * } else if( slope < .6 ) { * block = Block.Red; * } else { * block = Block.Black; * } * for( int i = level; i >= 0; i-- ) { * map.SetBlock( x, y, i, block ); * } * } * }*/ float[,] altmap = null; if (args.MaxHeightVariation != 0 || args.MaxDepthVariation != 0) { ReportProgress(5, "Heightmap Processing: Randomizing"); altmap = new float[map.WidthX, map.WidthY]; int blendmapDetailSize = (int)Math.Log(Math.Max(args.WidthX, args.WidthY), 2) - 2; new Noise(rand.Next(), NoiseInterpolationMode.Cosine).PerlinNoise2D(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--) { 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 = (args.MaxHeightVariation != 0 ? (args.MaxHeight + altmap[x, y] * args.MaxHeightVariation) : 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"); Map outMap = new Map(null, map.WidthX, map.WidthY, map.Height, false) { Blocks = (byte[])map.Blocks.Clone() }; Forester treeGen = new Forester(new ForesterArgs { InMap = map, OutMap = outMap, Rand = rand, TreeCount = (int)(map.WidthX * map.WidthY * 4 / (1024f * (args.TreeSpacingMax + args.TreeSpacingMin) / 2)), Operation = Forester.ForesterOperation.Add, GroundSurfaceBlock = bGroundSurface }); treeGen.Generate(); map = outMap; GenerateTrees(map); } ReportProgress(0, "Generation complete"); map.ResetSpawn(); map.SetMeta("_Origin", "GeneratorName", "fCraft"); map.SetMeta("_Origin", "GeneratorVersion", Updater.CurrentRelease.VersionString); map.SetMeta("_Origin", "GeneratorParams", args.Serialize().ToString(SaveOptions.DisableFormatting)); return(map); }