2011-04-13 07:51:13 +00:00
|
|
|
|
using System;
|
|
|
|
|
using Substrate;
|
2012-04-29 00:35:57 +00:00
|
|
|
|
using Substrate.Nbt;
|
|
|
|
|
using Substrate.Core;
|
|
|
|
|
using System.IO;
|
2011-04-13 07:51:13 +00:00
|
|
|
|
|
|
|
|
|
// FlatMap is an example of generating worlds from scratch with Substrate.
|
|
|
|
|
// It will produce a completely flat, solid map with grass, dirt, stone,
|
|
|
|
|
// and bedrock layers. On a powerful workstation, creating 400 of these
|
|
|
|
|
// chunks only takes a few seconds.
|
|
|
|
|
|
|
|
|
|
namespace FlatMap
|
|
|
|
|
{
|
|
|
|
|
class Program
|
|
|
|
|
{
|
|
|
|
|
static void Main (string[] args)
|
|
|
|
|
{
|
2012-04-29 00:35:57 +00:00
|
|
|
|
if (args.Length < 2) {
|
|
|
|
|
Console.WriteLine("Usage: flatmap <type> <target_dir>");
|
|
|
|
|
Console.WriteLine("Available Types: alpha, beta, anvil");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string dest = args[1];
|
2011-04-13 08:46:06 +00:00
|
|
|
|
int xmin = -20;
|
|
|
|
|
int xmax = 20;
|
|
|
|
|
int zmin = -20;
|
|
|
|
|
int zmaz = 20;
|
2011-04-13 07:51:13 +00:00
|
|
|
|
|
2012-04-29 00:35:57 +00:00
|
|
|
|
NbtVerifier.InvalidTagType += (e) =>
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Invalid Tag Type: " + e.TagName + " [" + e.Tag + "]");
|
|
|
|
|
};
|
|
|
|
|
NbtVerifier.InvalidTagValue += (e) =>
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Invalid Tag Value: " + e.TagName + " [" + e.Tag + "]");
|
|
|
|
|
};
|
|
|
|
|
NbtVerifier.MissingTag += (e) =>
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Missing Tag: " + e.TagName);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!Directory.Exists(dest))
|
|
|
|
|
Directory.CreateDirectory(dest);
|
|
|
|
|
|
2011-04-13 07:51:13 +00:00
|
|
|
|
// This will instantly create any necessary directory structure
|
2012-04-29 00:35:57 +00:00
|
|
|
|
NbtWorld world;
|
|
|
|
|
switch (args[0]) {
|
|
|
|
|
case "alpha": world = AlphaWorld.Create(dest); break;
|
|
|
|
|
case "beta": world = BetaWorld.Create(dest); break;
|
|
|
|
|
case "anvil": world = AnvilWorld.Create(dest); break;
|
|
|
|
|
default: throw new Exception("Invalid world type specified.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IChunkManager cm = world.GetChunkManager();
|
2011-04-13 07:51:13 +00:00
|
|
|
|
|
|
|
|
|
// We can set different world parameters
|
|
|
|
|
world.Level.LevelName = "Flatlands";
|
2012-04-29 00:35:57 +00:00
|
|
|
|
world.Level.Spawn = new SpawnPoint(20, 70, 20);
|
2011-06-02 07:35:25 +00:00
|
|
|
|
|
|
|
|
|
// world.Level.SetDefaultPlayer();
|
|
|
|
|
// We'll let MC create the player for us, but you could use the above
|
|
|
|
|
// line to create the SSP player entry in level.dat.
|
2011-04-13 07:51:13 +00:00
|
|
|
|
|
|
|
|
|
// We'll create chunks at chunk coordinates xmin,zmin to xmax,zmax
|
|
|
|
|
for (int xi = xmin; xi < xmax; xi++) {
|
|
|
|
|
for (int zi = zmin; zi < zmaz; zi++) {
|
|
|
|
|
// This line will create a default empty chunk, and create a
|
|
|
|
|
// backing region file if necessary (which will immediately be
|
|
|
|
|
// written to disk)
|
|
|
|
|
ChunkRef chunk = cm.CreateChunk(xi, zi);
|
|
|
|
|
|
2011-04-13 08:46:06 +00:00
|
|
|
|
// This will suppress generating caves, ores, and all those
|
|
|
|
|
// other goodies.
|
|
|
|
|
chunk.IsTerrainPopulated = true;
|
|
|
|
|
|
2011-04-13 07:51:13 +00:00
|
|
|
|
// Auto light recalculation is horrifically bad for creating
|
|
|
|
|
// chunks from scratch, because we're placing thousands
|
|
|
|
|
// of blocks. Turn it off.
|
2011-05-13 03:09:57 +00:00
|
|
|
|
chunk.Blocks.AutoLight = false;
|
2011-04-13 07:51:13 +00:00
|
|
|
|
|
|
|
|
|
// Set the blocks
|
|
|
|
|
FlatChunk(chunk, 64);
|
|
|
|
|
|
|
|
|
|
// Reset and rebuild the lighting for the entire chunk at once
|
2012-04-29 00:35:57 +00:00
|
|
|
|
chunk.Blocks.RebuildHeightMap();
|
2011-05-13 03:09:57 +00:00
|
|
|
|
chunk.Blocks.RebuildBlockLight();
|
2011-05-13 03:21:53 +00:00
|
|
|
|
chunk.Blocks.RebuildSkyLight();
|
2011-04-13 07:51:13 +00:00
|
|
|
|
|
|
|
|
|
Console.WriteLine("Built Chunk {0},{1}", chunk.X, chunk.Z);
|
|
|
|
|
|
|
|
|
|
// Save the chunk to disk so it doesn't hang around in RAM
|
|
|
|
|
cm.Save();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Save all remaining data (including a default level.dat)
|
|
|
|
|
// If we didn't save chunks earlier, they would be saved here
|
|
|
|
|
world.Save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void FlatChunk (ChunkRef chunk, int height)
|
|
|
|
|
{
|
|
|
|
|
// Create bedrock
|
|
|
|
|
for (int y = 0; y < 2; y++) {
|
|
|
|
|
for (int x = 0; x < 16; x++) {
|
|
|
|
|
for (int z = 0; z < 16; z++) {
|
2011-05-13 03:21:53 +00:00
|
|
|
|
chunk.Blocks.SetID(x, y, z, (int)BlockType.BEDROCK);
|
2011-04-13 07:51:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create stone
|
|
|
|
|
for (int y = 2; y < height - 5; y++) {
|
|
|
|
|
for (int x = 0; x < 16; x++) {
|
|
|
|
|
for (int z = 0; z < 16; z++) {
|
2011-05-13 03:21:53 +00:00
|
|
|
|
chunk.Blocks.SetID(x, y, z, (int)BlockType.STONE);
|
2011-04-13 07:51:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create dirt
|
|
|
|
|
for (int y = height - 5; y < height - 1; y++) {
|
|
|
|
|
for (int x = 0; x < 16; x++) {
|
|
|
|
|
for (int z = 0; z < 16; z++) {
|
2011-05-13 03:21:53 +00:00
|
|
|
|
chunk.Blocks.SetID(x, y, z, (int)BlockType.DIRT);
|
2011-04-13 07:51:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create grass
|
|
|
|
|
for (int y = height - 1; y < height; y++) {
|
|
|
|
|
for (int x = 0; x < 16; x++) {
|
|
|
|
|
for (int z = 0; z < 16; z++) {
|
2011-05-13 03:21:53 +00:00
|
|
|
|
chunk.Blocks.SetID(x, y, z, (int)BlockType.GRASS);
|
2011-04-13 07:51:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|