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);
}