Final terrain generation PR fixes

This commit is contained in:
Daniel Vidmar 2015-02-24 20:30:28 -05:00
parent dff8348bc3
commit 30392fae69
22 changed files with 151 additions and 182 deletions

View File

@ -19,5 +19,7 @@ namespace TrueCraft.API.World
byte WaterBlock { get; }
byte SurfaceBlock { get; }
byte FillerBlock { get; }
int SurfaceDepth { get; }
int FillerDepth { get; }
}
}

View File

@ -21,7 +21,7 @@ namespace TrueCraft.Core.Logic.Blocks
public override byte Luminance { get { return 0; } }
public override bool Opaque { get { return false; } }
public override bool Opaque { get { return true; } } // TODO: Distinguish between opaque and instantly destroyable
public override byte LightModifier { get { return 255; } }

View File

@ -206,7 +206,7 @@ namespace TrueCraft.Core.Logic.Blocks
var currentLevel = world.GetMetadata(coords);
var blockBelow = world.BlockRepository.GetBlockProvider(world.GetBlockID(coords + Coordinates3D.Down));
if (!blockBelow.Opaque && blockBelow.ID != FlowingID && blockBelow.ID != StillID)
if (blockBelow.Hardness == 0 && blockBelow.ID != FlowingID && blockBelow.ID != StillID)
{
outwardFlow.Add(new LiquidFlow(coords + Coordinates3D.Down, 1));
if (currentLevel != 0)
@ -232,7 +232,7 @@ namespace TrueCraft.Core.Logic.Blocks
continue;
var check = new Coordinates3D(x: x, z: z) + Coordinates3D.Down;
var c = world.BlockRepository.GetBlockProvider(world.GetBlockID(check + coords));
if (!c.Opaque)
if (c.Hardness == 0)
{
if (!LineOfSight(world, check + coords, coords))
continue;
@ -288,7 +288,7 @@ namespace TrueCraft.Core.Logic.Blocks
for (int i = 0; i < Neighbors.Length; i++)
{
var b = world.BlockRepository.GetBlockProvider(world.GetBlockID(coords + Neighbors[i]));
if (!b.Opaque && b.ID != StillID && b.ID != FlowingID)
if (b.Hardness == 0 && b.ID != StillID && b.ID != FlowingID)
outwardFlow.Add(new LiquidFlow(Neighbors[i] + coords, (byte)(currentLevel + 1)));
}
}
@ -310,7 +310,7 @@ namespace TrueCraft.Core.Logic.Blocks
do
{
var p = world.BlockRepository.GetBlockProvider(world.GetBlockID(candidate));
if (p.Opaque)
if (p.Hardness != 0)
return false;
candidate.Z += direction.Z;
} while (target.Z != candidate.Z);

View File

@ -72,14 +72,22 @@ namespace TrueCraft.Core.TerrainGen.Biomes
/// <summary>
/// The main surface block used for the terrain of the biome.
/// Note: This field may be removed in the future.
/// </summary>
public virtual byte SurfaceBlock { get { return GrassBlock.BlockID; } }
/// <summary>
/// The main "filler" block found under the surface block in the terrain of the biome.
/// Note: This field may be removed in the future.
/// </summary>
public virtual byte FillerBlock { get { return StoneBlock.BlockID; } }
public virtual byte FillerBlock { get { return DirtBlock.BlockID; } }
/// <summary>
/// The depth of the surface block layer
/// </summary>
public virtual int SurfaceDepth { get { return 1; } }
/// <summary>
/// The depth of the "filler" blocks located below the surface block layer
/// </summary>
public virtual int FillerDepth { get { return 4; } }
}
}

View File

@ -57,5 +57,13 @@ namespace TrueCraft.Core.TerrainGen.Biomes
return SandstoneBlock.BlockID;
}
}
public override int SurfaceDepth
{
get
{
return 4;
}
}
}
}

View File

@ -33,21 +33,5 @@ namespace TrueCraft.Core.TerrainGen.Biomes
return new PlantSpecies[] { PlantSpecies.TallGrass };
}
}
public override byte SurfaceBlock
{
get
{
return GrassBlock.BlockID;
}
}
public override byte FillerBlock
{
get
{
return DirtBlock.BlockID;
}
}
}
}

View File

@ -33,21 +33,5 @@ namespace TrueCraft.Core.TerrainGen.Biomes
return new TreeSpecies[] { TreeSpecies.Oak };
}
}
public override byte SurfaceBlock
{
get
{
return GrassBlock.BlockID;
}
}
public override byte FillerBlock
{
get
{
return DirtBlock.BlockID;
}
}
}
}

View File

@ -49,21 +49,5 @@ namespace TrueCraft.Core.TerrainGen.Biomes
return new PlantSpecies[] { PlantSpecies.Fern, PlantSpecies.TallGrass };
}
}
public override byte SurfaceBlock
{
get
{
return GrassBlock.BlockID;
}
}
public override byte FillerBlock
{
get
{
return DirtBlock.BlockID;
}
}
}
}

View File

@ -49,21 +49,5 @@ namespace TrueCraft.Core.TerrainGen.Biomes
return 50;
}
}
public override byte SurfaceBlock
{
get
{
return GrassBlock.BlockID;
}
}
public override byte FillerBlock
{
get
{
return DirtBlock.BlockID;
}
}
}
}

View File

@ -33,21 +33,5 @@ namespace TrueCraft.Core.TerrainGen.Biomes
return new PlantSpecies[] { PlantSpecies.Fern, PlantSpecies.TallGrass };
}
}
public override byte SurfaceBlock
{
get
{
return GrassBlock.BlockID;
}
}
public override byte FillerBlock
{
get
{
return DirtBlock.BlockID;
}
}
}
}

View File

@ -41,21 +41,5 @@ namespace TrueCraft.Core.TerrainGen.Biomes
return new PlantSpecies[0];
}
}
public override byte SurfaceBlock
{
get
{
return GrassBlock.BlockID;
}
}
public override byte FillerBlock
{
get
{
return DirtBlock.BlockID;
}
}
}
}

View File

@ -41,21 +41,5 @@ namespace TrueCraft.Core.TerrainGen.Biomes
return new PlantSpecies[] { PlantSpecies.SugarCane };
}
}
public override byte SurfaceBlock
{
get
{
return GrassBlock.BlockID;
}
}
public override byte FillerBlock
{
get
{
return DirtBlock.BlockID;
}
}
}
}

View File

@ -34,19 +34,11 @@ namespace TrueCraft.Core.TerrainGen.Biomes
}
}
public override byte SurfaceBlock
public override double TreeDensity
{
get
{
return GrassBlock.BlockID;
}
}
public override byte FillerBlock
{
get
{
return DirtBlock.BlockID;
return 5;
}
}
}

View File

@ -25,16 +25,18 @@ namespace TrueCraft.Core.TerrainGen.Decorators
IBiomeProvider Biome = biomes.GetBiome(chunk.Biomes[X * Chunk.Width + Z]);
var BlockX = MathHelper.ChunkToBlockX(X, chunk.Coordinates.X);
var BlockZ = MathHelper.ChunkToBlockZ(Z, chunk.Coordinates.Z);
var Height = chunk.HeightMap[X * Chunk.Width + Z] + 1;
if (Biome.Plants.Contains(PlantSpecies.Cactus) && ChanceNoise.Value2D(BlockX, BlockZ) > 1.3)
var Height = chunk.HeightMap[X * Chunk.Width + Z];
if (Biome.Plants.Contains(PlantSpecies.Cactus) && ChanceNoise.Value2D(BlockX, BlockZ) > 1.7)
{
if (chunk.GetBlockID(new Coordinates3D(X, Height - 1, Z)).Equals(SandBlock.BlockID))
Coordinates3D BlockLocation = new Coordinates3D(X, Height, Z);
Coordinates3D CactiPosition = BlockLocation + Coordinates3D.Up;
if (chunk.GetBlockID(BlockLocation).Equals(SandBlock.BlockID))
{
var HeightChance = ChanceNoise.Value2D(BlockX, BlockZ);
var CactusHeight = (HeightChance < 1.4) ? 2 : 3;
for (int Y = Height; Y < Height + CactusHeight; Y++)
for (int Y = CactiPosition.Y; Y < CactiPosition.Y + CactusHeight; Y++)
{
chunk.SetBlockID(new Coordinates3D(X, Y, Z), CactusBlock.BlockID);
chunk.SetBlockID(new Coordinates3D(CactiPosition.X, Y, CactiPosition.Z), CactusBlock.BlockID);
}
}
}

View File

@ -23,18 +23,20 @@ namespace TrueCraft.Core.TerrainGen.Decorators
var Height = chunk.HeightMap[X * Chunk.Width + Z];
for (int Y = Height; Y < Chunk.Height; Y++)
{
if (Height < Chunk.Height - 1)
Coordinates3D Location = new Coordinates3D(X, Y, Z);
if (chunk.GetBlockID(Location).Equals(StationaryWaterBlock.BlockID) || chunk.GetBlockID(Location).Equals(WaterBlock.BlockID))
{
if (chunk.GetBlockID(new Coordinates3D(X, Height, Z)).Equals(StationaryWaterBlock.BlockID))
chunk.SetBlockID(Location, IceBlock.BlockID);
}
else
{
if (chunk.GetBlockID(Location).Equals(IceBlock.BlockID) && CoverIce(chunk, biomes, Location))
{
chunk.SetBlockID(new Coordinates3D(X, Height, Z), IceBlock.BlockID);
chunk.SetBlockID((Location + Coordinates3D.Up), SnowfallBlock.BlockID);
}
else
else if (!chunk.GetBlockID(Location).Equals(SnowfallBlock.BlockID) && !chunk.GetBlockID(Location).Equals(AirBlock.BlockID))
{
if (!chunk.GetBlockID(new Coordinates3D(X, Height, Z)).Equals(SnowfallBlock.BlockID) && !chunk.GetBlockID(new Coordinates3D(X, Height, Z)).Equals(0))
{
chunk.SetBlockID(new Coordinates3D(X, Height + 1, Z), SnowfallBlock.BlockID);
}
chunk.SetBlockID((Location + Coordinates3D.Up), SnowfallBlock.BlockID);
}
}
}
@ -42,5 +44,26 @@ namespace TrueCraft.Core.TerrainGen.Decorators
}
}
}
bool CoverIce(IChunk chunk, IBiomeRepository biomes, Coordinates3D Location)
{
var MaxDistance = 4;
var Surrounding = new[] {
Location + new Coordinates3D(-MaxDistance, 0, 0),
Location + new Coordinates3D(MaxDistance, 0, 0),
Location + new Coordinates3D(0, 0, MaxDistance),
Location + new Coordinates3D(0, 0, -MaxDistance),
};
for (int I = 0; I < Surrounding.Length; I++)
{
Coordinates3D Check = Surrounding[I];
if (Check.X < 0 || Check.X >= Chunk.Width || Check.Z < 0 || Check.Z >= Chunk.Depth || Check.Y < 0 || Check.Y >= Chunk.Height)
return false;
IBiomeProvider Biome = biomes.GetBiome(chunk.Biomes[Check.X * Chunk.Width + Check.Z]);
if (chunk.GetBlockID(Check).Equals(Biome.SurfaceBlock) || chunk.GetBlockID(Check).Equals(Biome.FillerBlock))
return true;
}
return false;
}
}
}

View File

@ -97,7 +97,7 @@ namespace TrueCraft.Core.TerrainGen.Decorators
if (X >= 0 && Z >= 0 && Y >= Data.MinY && X < Chunk.Width && Y < Data.MaxY && Z < Chunk.Depth)
{
IBiomeProvider Biome = biomes.GetBiome(chunk.Biomes[(int)(X * Chunk.Width + Z)]);
if (Biome.Ores.Contains(Data.Type) && chunk.GetBlockID(new Coordinates3D((int)X, (int)Y, (int)Z)).Equals(GlassBlock.BlockID))
if (Biome.Ores.Contains(Data.Type) && chunk.GetBlockID(new Coordinates3D((int)X, (int)Y, (int)Z)).Equals(StoneBlock.BlockID))
{
chunk.SetBlockID(new Coordinates3D((int)X, (int)Y, (int)Z), Data.ID);
}
@ -128,7 +128,7 @@ namespace TrueCraft.Core.TerrainGen.Decorators
if (NewX >= 0 && NewZ >= 0 && NewY >= Data.MinY && NewX < Chunk.Width && NewY < Data.MaxY && NewZ < Chunk.Depth)
{
IBiomeProvider Biome = biomes.GetBiome(chunk.Biomes[NewX * Chunk.Width + NewZ]);
if (Biome.Ores.Contains(Data.Type) && chunk.GetBlockID(new Coordinates3D((int)NewX, (int)NewY, (int)NewZ)).Equals(GlassBlock.BlockID))
if (Biome.Ores.Contains(Data.Type) && chunk.GetBlockID(new Coordinates3D((int)NewX, (int)NewY, (int)NewZ)).Equals(StoneBlock.BlockID))
{
chunk.SetBlockID(new Coordinates3D((int)NewX, (int)NewY, (int)NewZ), Data.ID);
}

View File

@ -26,7 +26,6 @@ namespace TrueCraft.Core.TerrainGen.Decorators
var BlockX = MathHelper.ChunkToBlockX(X, chunk.Coordinates.X);
var BlockZ = MathHelper.ChunkToBlockZ(Z, chunk.Coordinates.Z);
var Height = chunk.HeightMap[X * Chunk.Width + Z];
Coordinates3D Below = new Coordinates3D(X, Height, Z) + Coordinates3D.Down;
if (Noise.Value2D(BlockX, BlockZ) > 0.25)
{
Coordinates3D BlockLocation = new Coordinates3D(X, Height, Z);

View File

@ -24,18 +24,24 @@ namespace TrueCraft.Core.TerrainGen.Decorators
{
Coordinates3D BlockLocation = new Coordinates3D(X, Y, Z);
int BlockID = chunk.GetBlockID(BlockLocation);
if (BlockID.Equals(0))
if (BlockID.Equals(AirBlock.BlockID))
{
chunk.SetBlockID(BlockLocation, Biome.WaterBlock);
Coordinates3D Below = BlockLocation + Coordinates3D.Down;
if (!chunk.GetBlockID(Below).Equals(0) && !chunk.GetBlockID(Below).Equals(Biome.WaterBlock))
if (!chunk.GetBlockID(Below).Equals(AirBlock.BlockID) && !chunk.GetBlockID(Below).Equals(Biome.WaterBlock))
{
Random R = new Random(world.Seed);
double Chance = R.NextDouble();
if (Chance < 0.15)
chunk.SetBlockID(Below, ClayBlock.BlockID);
else
chunk.SetBlockID(Below, SandBlock.BlockID);
if (!Biome.WaterBlock.Equals(LavaBlock.BlockID) && !Biome.WaterBlock.Equals(StationaryLavaBlock.BlockID))
{
Random R = new Random(world.Seed);
if (R.Next(100) < 40)
{
chunk.SetBlockID(Below, ClayBlock.BlockID);
}
else
{
chunk.SetBlockID(Below, SandBlock.BlockID);
}
}
}
}
}

View File

@ -20,37 +20,49 @@ namespace TrueCraft.Core.TerrainGen
BiomeRepository Biomes = new BiomeRepository();
Perlin HighNoise = new Perlin();
Perlin LowNoise = new Perlin();
Perlin BottomNoise = new Perlin();
ClampNoise HighClamp;
ClampNoise LowClamp;
ClampNoise BottomClamp;
ModifyNoise Modified;
private int GroundLevel = 50;
public NewGenerator(bool SingleBiome = false, byte GenerateBiome = (byte)Biome.Plains)
{
this.SingleBiome = SingleBiome;
this.GenerationBiome = GenerateBiome;
HighNoise.Persistance = 1;
HighNoise.Frequency = 0.023;
HighNoise.Amplitude = 14;
HighNoise.Frequency = 0.013;
HighNoise.Amplitude = 10;
HighNoise.Octaves = 2;
HighNoise.Lacunarity = 2;
LowNoise.Persistance = 1;
LowNoise.Frequency = 0.023;
LowNoise.Amplitude = 5;
LowNoise.Frequency = 0.008;
LowNoise.Amplitude = 14;
LowNoise.Octaves = 2;
LowNoise.Lacunarity = 2;
HighClamp = new ClampNoise(HighClamp);
HighClamp.MinValue = 0;
HighClamp.MaxValue = 20;
LowNoise.Lacunarity = 2.5;
BottomNoise.Persistance = 0.5;
BottomNoise.Frequency = 0.013;
BottomNoise.Amplitude = 5;
BottomNoise.Octaves = 2;
BottomNoise.Lacunarity = 1.5;
HighClamp = new ClampNoise(HighNoise);
HighClamp.MinValue = -10;
HighClamp.MaxValue = 25;
LowClamp = new ClampNoise(LowNoise);
LowClamp.MinValue = -20;
LowClamp.MaxValue = 20;
LowClamp.MinValue = -30;
LowClamp.MaxValue = 30;
BottomClamp = new ClampNoise(BottomNoise);
BottomClamp.MinValue = -20;
BottomClamp.MaxValue = 5;
Modified = new ModifyNoise(HighClamp, LowClamp, NoiseModifier.Add);
ChunkDecorators = new List<IChunkDecorator>();
ChunkDecorators.Add(new WaterDecorator());
ChunkDecorators.Add(new OreDecorator());
ChunkDecorators.Add(new TreeDecorator());
ChunkDecorators.Add(new FreezeDecorator());
ChunkDecorators.Add(new PlantDecorator());
ChunkDecorators.Add(new CactusDecorator());
ChunkDecorators.Add(new SugarCaneDecorator());
ChunkDecorators.Add(new OreDecorator());
ChunkDecorators.Add(new DungeonDecorator(GroundLevel));
}
@ -60,13 +72,12 @@ namespace TrueCraft.Core.TerrainGen
public byte GenerationBiome { get; private set; }
public IChunk GenerateChunk(IWorld world, Coordinates2D coordinates)
{
int FeaturePointDistance = 90;
CellNoise Worley = new CellNoise();
Worley.Seed = world.Seed;
int FeaturePointDistance = 400;
int Seed = world.Seed;
CellNoise Worley = new CellNoise();
Worley.Seed = Seed;
HighNoise.Seed = Seed;
LowNoise.Seed = Seed;
ModifyNoise Modified = new ModifyNoise(HighNoise, LowNoise, NoiseModifier.Add);
var chunk = new Chunk(coordinates);
for (int X = 0; X < 16; X++)
{
@ -74,6 +85,20 @@ namespace TrueCraft.Core.TerrainGen
{
var BlockX = MathHelper.ChunkToBlockX(X, coordinates.X);
var BlockZ = MathHelper.ChunkToBlockZ(Z, coordinates.Z);
double LowClampMid = LowClamp.MaxValue - ((LowClamp.MaxValue + LowClamp.MinValue) / 2);
double LowClampRange = 5;
double LowClampValue = LowClamp.Value2D(BlockX, BlockZ);
if (LowClampValue > LowClampMid - LowClampRange && LowClampValue < LowClampMid + LowClampRange)
{
InvertNoise NewPrimary = new InvertNoise(HighClamp);
Modified.PrimaryNoise = NewPrimary;
}
else
{
//reset it after modifying the values
Modified = new ModifyNoise(HighClamp, LowClamp, NoiseModifier.Add);
}
Modified = new ModifyNoise(Modified, BottomClamp, NoiseModifier.Subtract);
var CellValue = Worley.Value2D(BlockX, BlockZ);
var Location = new Coordinates2D(BlockX, BlockZ);
if (world.BiomeDiagram.BiomeCells.Count < 1 || CellValue.Equals(1) && world.BiomeDiagram.ClosestCellPoint(Location) >= FeaturePointDistance)
@ -87,7 +112,8 @@ namespace TrueCraft.Core.TerrainGen
IBiomeProvider Biome = Biomes.GetBiome(BiomeID);
chunk.Biomes[X * Chunk.Width + Z] = BiomeID;
var Height = GetHeight(BlockX, BlockZ, Modified);
var Height = GetHeight(BlockX, BlockZ);
var SurfaceHeight = Height - Biome.SurfaceDepth;
chunk.HeightMap[X * Chunk.Width + Z] = Height;
for (int Y = 0; Y <= Height; Y++)
{
@ -97,13 +123,13 @@ namespace TrueCraft.Core.TerrainGen
}
else
{
if (Y.Equals(Height))
if (Y.Equals(Height) || Y < Height && Y > SurfaceHeight)
{
chunk.SetBlockID(new Coordinates3D(X, Y, Z), Biome.SurfaceBlock);
}
else
{
if (Y < Height && Y > Height - 4)
if (Y > SurfaceHeight - Biome.FillerDepth)
{
chunk.SetBlockID(new Coordinates3D(X, Y, Z), Biome.FillerBlock);
}
@ -121,7 +147,7 @@ namespace TrueCraft.Core.TerrainGen
ChunkDecorator.Decorate(world, chunk, Biomes);
}
var SpawnOffset = 2;
var SpawnPointHeight = GetHeight(0, 0, Modified);
var SpawnPointHeight = GetHeight(0, 0);
if (SpawnPointHeight + SpawnOffset < Chunk.Height)
SpawnPointHeight += SpawnOffset;
SpawnPoint = new Vector3(0, SpawnPointHeight, 0);
@ -137,9 +163,9 @@ namespace TrueCraft.Core.TerrainGen
return world.BiomeDiagram.GetBiome(Location);
}
int GetHeight(int X, int Z, INoise Noise)
int GetHeight(int X, int Z)
{
var NoiseValue = Noise.Value2D(X, Z) + GroundLevel;
var NoiseValue = Modified.Value2D(X, Z) + GroundLevel;
if (NoiseValue < 0)
NoiseValue = GroundLevel;
if (NoiseValue > Chunk.Height)

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using TrueCraft.API.World;
using TrueCraft.API;
using TrueCraft.Core.World;
namespace TrueCraft.Core.TerrainGen.Noise
{
@ -52,9 +54,20 @@ namespace TrueCraft.Core.TerrainGen.Noise
return Point0 * (1 - T) + Point1 * T;
}
public static double[] ExpandData()
public static double BiLinearInterpolate(double X, double Y, double Point00, double Point01, double Point10, double Point11)
{
return new double[0];
double Point0 = LinearInterpolate(Point00, Point10, X);
double Point1 = LinearInterpolate(Point01, Point11, X);
return LinearInterpolate(Point0, Point1, Y);
}
public static double TriLinearInterpolate(double X, double Y, double Z, double Point000, double Point001, double Point010, double Point100, double Point011, double Point101, double Point110, double Point111)
{
double Point0 = BiLinearInterpolate(X, Y, Point000, Point001, Point100, Point101);
double Point1 = BiLinearInterpolate(X, Y, Point010, Point011, Point110, Point111);
return LinearInterpolate(Point0, Point1, Z);
}
}

View File

@ -39,6 +39,11 @@ namespace TrueCraft.Core.TerrainGen.Noise
}
public OpenSimplex(long Seed)
{
SetSeed(Seed);
}
public void SetSeed(long Seed)
{
Perm = new short[256];
PermGradIndex3D = new short[256];
@ -48,7 +53,8 @@ namespace TrueCraft.Core.TerrainGen.Noise
Seed = Seed * 6364136223846793005L + 1442695040888963407L;
Seed = Seed * 6364136223846793005L + 1442695040888963407L;
Seed = Seed * 6364136223846793005L + 1442695040888963407L;
for (int I = 255; I >= 0; I--) {
for (int I = 255; I >= 0; I--)
{
Seed = Seed * 6364136223846793005L + 1442695040888963407L;
int R = (int)((Seed + 31) % (I + 1));
if (R < 0)

View File

@ -21,10 +21,6 @@ namespace TrueCraft
{
// TODO: Make this more flexible
var server = new MultiplayerServer();
#if DEBUG
if (Directory.Exists("world"))
Directory.Delete("world", true);
#endif
IWorld world;
try
{