Add world manifests

These include the spawn point, seed, and terrain generator so that you
can load saved worlds with all the right details.
This commit is contained in:
Drew DeVault 2015-04-13 17:41:57 -06:00
parent 4d5509b734
commit 65deecd131
8 changed files with 79 additions and 56 deletions

View File

@ -10,6 +10,6 @@ namespace TrueCraft.API.World
{
IList<IChunkDecorator> ChunkDecorators { get; }
IChunk GenerateChunk(IWorld world, Coordinates2D coordinates);
Vector3 SpawnPoint { get; }
Coordinates3D GetSpawn(IWorld world);
}
}

View File

@ -14,6 +14,7 @@ namespace TrueCraft.API.World
int Seed { get; set; }
IBiomeMap BiomeDiagram { get; set; }
IChunkProvider ChunkProvider { get; set; }
Coordinates3D SpawnPoint { get; set; }
long Time { get; set; }
event EventHandler<BlockChangeEventArgs> BlockChanged;

View File

@ -19,7 +19,6 @@ namespace TrueCraft.Core.TerrainGen
public FlatlandGenerator()
{
GeneratorOptions = DefaultGeneratorOptions;
SpawnPoint = new Vector3(0, 5, 0);
ChunkDecorators = new List<IChunkDecorator>();
}
@ -58,7 +57,6 @@ namespace TrueCraft.Core.TerrainGen
Layers.Add(generatorLayer);
}
Biome = (Biome)byte.Parse(parts[2]);
SpawnPoint = new Vector3(0, y, 0);
}
public IChunk GenerateChunk(IWorld world, Coordinates2D position)
@ -97,7 +95,10 @@ namespace TrueCraft.Core.TerrainGen
public IList<IChunkDecorator> ChunkDecorators { get; set; }
public Vector3 SpawnPoint { get; set; }
public Coordinates3D GetSpawn(IWorld world)
{
return Coordinates3D.Up * 5;
}
protected class GeneratorLayer
{

View File

@ -16,7 +16,7 @@ namespace TrueCraft.Core.TerrainGen
/// <summary>
/// This terrain generator is still under heavy development. Use at your own risk.
/// </summary>
public class NewGenerator : IChunkProvider
public class StandardGenerator : IChunkProvider
{
BiomeRepository Biomes = new BiomeRepository();
Perlin HighNoise = new Perlin();
@ -27,7 +27,8 @@ namespace TrueCraft.Core.TerrainGen
ClampNoise BottomClamp;
ModifyNoise Modified;
private int GroundLevel = 50;
public NewGenerator(bool SingleBiome = false, byte GenerateBiome = (byte)Biome.Plains)
public StandardGenerator(bool SingleBiome = false, byte GenerateBiome = (byte)Biome.Plains)
{
this.SingleBiome = SingleBiome;
this.GenerationBiome = GenerateBiome;
@ -71,25 +72,26 @@ namespace TrueCraft.Core.TerrainGen
public Vector3 SpawnPoint { get; private set; }
public bool SingleBiome { get; private set; }
public byte GenerationBiome { get; private set; }
public IChunk GenerateChunk(IWorld world, Coordinates2D coordinates)
{
int FeaturePointDistance = 400;
int Seed = world.Seed;
CellNoise Worley = new CellNoise();
Worley.Seed = Seed;
HighNoise.Seed = Seed;
LowNoise.Seed = Seed;
const int featurePointDistance = 400;
int seed = world.Seed;
var worley = new CellNoise();
worley.Seed = seed;
HighNoise.Seed = seed;
LowNoise.Seed = seed;
var chunk = new Chunk(coordinates);
for (int X = 0; X < 16; X++)
{
for (int Z = 0; Z < 16; Z++)
{
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)
var blockX = MathHelper.ChunkToBlockX(X, coordinates.X);
var blockZ = MathHelper.ChunkToBlockZ(Z, coordinates.Z);
const double lowClampRange = 5;
double lowClampMid = LowClamp.MaxValue - ((LowClamp.MaxValue + LowClamp.MinValue) / 2);
double lowClampValue = LowClamp.Value2D(blockX, blockZ);
if (lowClampValue > lowClampMid - lowClampRange && lowClampValue < lowClampMid + lowClampRange)
{
InvertNoise NewPrimary = new InvertNoise(HighClamp);
Modified.PrimaryNoise = NewPrimary;
@ -100,23 +102,23 @@ namespace TrueCraft.Core.TerrainGen
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)
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)
{
byte ID = (SingleBiome) ? GenerationBiome : world.BiomeDiagram.GenerateBiome(Seed, Biomes, Location);
BiomeCell Cell = new BiomeCell(ID, Location);
byte id = (SingleBiome) ? GenerationBiome : world.BiomeDiagram.GenerateBiome(seed, Biomes, location);
BiomeCell Cell = new BiomeCell(id, location);
world.BiomeDiagram.AddCell(Cell);
}
var BiomeID = GetBiome(world, Location);
IBiomeProvider Biome = Biomes.GetBiome(BiomeID);
chunk.Biomes[X * Chunk.Width + Z] = BiomeID;
var biomeId = GetBiome(world, location);
IBiomeProvider Biome = Biomes.GetBiome(biomeId);
chunk.Biomes[X * Chunk.Width + Z] = biomeId;
var Height = GetHeight(BlockX, BlockZ);
var SurfaceHeight = Height - Biome.SurfaceDepth;
chunk.HeightMap[X * Chunk.Width + Z] = Height;
for (int Y = 0; Y <= Height; Y++)
var height = GetHeight(blockX, blockZ);
var surfaceHeight = height - Biome.SurfaceDepth;
chunk.HeightMap[X * Chunk.Width + Z] = height;
for (int Y = 0; Y <= height; Y++)
{
if (Y == 0)
{
@ -124,13 +126,13 @@ namespace TrueCraft.Core.TerrainGen
}
else
{
if (Y.Equals(Height) || Y < Height && Y > SurfaceHeight)
if (Y.Equals(height) || Y < height && Y > surfaceHeight)
{
chunk.SetBlockID(new Coordinates3D(X, Y, Z), Biome.SurfaceBlock);
}
else
{
if (Y > SurfaceHeight - Biome.FillerDepth)
if (Y > surfaceHeight - Biome.FillerDepth)
{
chunk.SetBlockID(new Coordinates3D(X, Y, Z), Biome.FillerBlock);
}
@ -144,29 +146,27 @@ namespace TrueCraft.Core.TerrainGen
}
}
foreach (IChunkDecorator ChunkDecorator in ChunkDecorators)
{
ChunkDecorator.Decorate(world, chunk, Biomes);
}
var SpawnOffset = 2;
var SpawnPointHeight = GetHeight(0, 0);
if (SpawnPointHeight + SpawnOffset < Chunk.Height)
SpawnPointHeight += SpawnOffset;
SpawnPoint = new Vector3(0, SpawnPointHeight, 0);
return chunk;
}
byte GetBiome(IWorld world, Coordinates2D Location)
public Coordinates3D GetSpawn(IWorld world)
{
if (SingleBiome)
{
return GenerationBiome;
}
return world.BiomeDiagram.GetBiome(Location);
var chunk = GenerateChunk(world, Coordinates2D.Zero);
var spawnPointHeight = chunk.HeightMap[0];
return new Coordinates3D(0, spawnPointHeight + 1, 0);
}
int GetHeight(int X, int Z)
byte GetBiome(IWorld world, Coordinates2D location)
{
var NoiseValue = Modified.Value2D(X, Z) + GroundLevel;
if (SingleBiome)
return GenerationBiome;
return world.BiomeDiagram.GetBiome(location);
}
int GetHeight(int x, int z)
{
var NoiseValue = Modified.Value2D(x, z) + GroundLevel;
if (NoiseValue < 0)
NoiseValue = GroundLevel;
if (NoiseValue > Chunk.Height)

View File

@ -206,7 +206,6 @@
<Compile Include="TerrainGen\Noise\Perlin.cs" />
<Compile Include="TerrainGen\Noise\ScaleNoise.cs" />
<Compile Include="TerrainGen\Noise\CellNoise.cs" />
<Compile Include="TerrainGen\NewGenerator.cs" />
<Compile Include="World\BiomeMap.cs" />
<Compile Include="World\Chunk.cs" />
<Compile Include="World\Region.cs" />
@ -309,6 +308,7 @@
<Compile Include="Logic\Blocks\FluidBlock.cs" />
<Compile Include="Entities\FallingSandEntity.cs" />
<Compile Include="Logic\Blocks\DoorBlock.cs" />
<Compile Include="TerrainGen\StandardGenerator.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

View File

@ -6,6 +6,7 @@ using System.Threading;
using TrueCraft.API;
using TrueCraft.API.World;
using TrueCraft.API.Logic;
using fNbt;
namespace TrueCraft.Core.World
{
@ -15,12 +16,14 @@ namespace TrueCraft.Core.World
public string Name { get; set; }
public int Seed { get; set; }
public Coordinates3D SpawnPoint { get; set; }
public string BaseDirectory { get; internal set; }
public IDictionary<Coordinates2D, IRegion> Regions { get; set; }
public IBiomeMap BiomeDiagram { get; set; }
public IChunkProvider ChunkProvider { get; set; }
public IBlockRepository BlockRepository { get; set; }
public DateTime BaseTime { get; set; }
public long Time
{
get
@ -47,6 +50,7 @@ namespace TrueCraft.Core.World
public World(string name, IChunkProvider chunkProvider) : this(name)
{
ChunkProvider = chunkProvider;
SpawnPoint = chunkProvider.GetSpawn(this);
}
public static World LoadWorld(string baseDirectory)
@ -55,6 +59,17 @@ namespace TrueCraft.Core.World
throw new DirectoryNotFoundException();
var world = new World(Path.GetFileName(baseDirectory));
world.BaseDirectory = baseDirectory;
if (File.Exists(Path.Combine(baseDirectory, "manifest.nbt")))
{
var file = new NbtFile(Path.Combine(baseDirectory, "manifest.nbt"));
world.SpawnPoint = new Coordinates3D(file.RootTag["SpawnPoint"]["X"].IntValue,
file.RootTag["SpawnPoint"]["Y"].IntValue,
file.RootTag["SpawnPoint"]["Z"].IntValue);
world.Seed = file.RootTag["Seed"].IntValue;
var providerName = file.RootTag["ChunkProvider"].StringValue;
var provider = (IChunkProvider)Activator.CreateInstance(Type.GetType(providerName), world);
world.ChunkProvider = provider;
}
return world;
}
@ -223,6 +238,16 @@ namespace TrueCraft.Core.World
foreach (var region in Regions)
region.Value.Save(Path.Combine(BaseDirectory, Region.GetRegionFileName(region.Key)));
}
var file = new NbtFile();
file.RootTag.Add(new NbtCompound("SpawnPoint", new[]
{
new NbtInt("X", this.SpawnPoint.X),
new NbtInt("Y", this.SpawnPoint.Y),
new NbtInt("Z", this.SpawnPoint.Z)
}));
file.RootTag.Add(new NbtInt("Seed", this.Seed));
file.RootTag.Add(new NbtString("ChunkProvider", this.ChunkProvider.GetType().FullName));
file.SaveToFile(Path.Combine(this.BaseDirectory, "manifest.nbt"), NbtCompression.ZLib);
}
public void Save(string path)
@ -230,11 +255,7 @@ namespace TrueCraft.Core.World
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
BaseDirectory = path;
lock (Regions)
{
foreach (var region in Regions)
region.Value.Save(Path.Combine(BaseDirectory, Region.GetRegionFileName(region.Key)));
}
Save();
}
public Coordinates3D FindBlockPosition(Coordinates3D coordinates, out IChunk chunk)

View File

@ -39,7 +39,7 @@ namespace TrueCraft.Handlers
client.QueuePacket(new LoginResponsePacket(0, 0, Dimension.Overworld));
client.UpdateChunks();
client.QueuePacket(new WindowItemsPacket(0, client.Inventory.GetSlots()));
client.Entity.Position = client.World.ChunkProvider.SpawnPoint;
client.Entity.Position = client.World.SpawnPoint;
client.QueuePacket(new SpawnPositionPacket((int)client.Entity.Position.X,
(int)client.Entity.Position.Y, (int)client.Entity.Position.Z));
client.QueuePacket(new SetPlayerPositionPacket(client.Entity.Position.X, client.Entity.Position.Y,

View File

@ -26,11 +26,11 @@ namespace TrueCraft
{
// TODO: Save and load levels, with seeds and everything
world = World.LoadWorld("world");
world.ChunkProvider = new NewGenerator();
world.ChunkProvider = new StandardGenerator();
}
catch
{
world = new World("default", new NewGenerator());
world = new World("default", new StandardGenerator());
world.Save("world");
}
server.AddWorld(world);