From 8cb719f2003438f557650afe2a4ac62cf64896aa Mon Sep 17 00:00:00 2001 From: Justin Aquadro Date: Wed, 13 Apr 2011 07:51:13 +0000 Subject: [PATCH] Added per-chunkref toggle for automatic relighting. Added manual whole-chunk relighting to chunkref, which severely improves generation speed of new chunks. Added first complete example, a "Flat Map" world generator. --- Substrate/SubstrateCS/Examples/Examples.sln | 56 +++++++++++ .../Examples/FlatMap/FlatMap.csproj | 52 ++++++++++ .../SubstrateCS/Examples/FlatMap/Program.cs | 99 +++++++++++++++++++ .../FlatMap/Properties/AssemblyInfo.cs | 36 +++++++ Substrate/SubstrateCS/Source/ChunkRef.cs | 73 ++++++++++++-- Substrate/SubstrateCS/Source/World.cs | 12 +++ 6 files changed, 319 insertions(+), 9 deletions(-) create mode 100644 Substrate/SubstrateCS/Examples/Examples.sln create mode 100644 Substrate/SubstrateCS/Examples/FlatMap/FlatMap.csproj create mode 100644 Substrate/SubstrateCS/Examples/FlatMap/Program.cs create mode 100644 Substrate/SubstrateCS/Examples/FlatMap/Properties/AssemblyInfo.cs diff --git a/Substrate/SubstrateCS/Examples/Examples.sln b/Substrate/SubstrateCS/Examples/Examples.sln new file mode 100644 index 0000000..b21f17f --- /dev/null +++ b/Substrate/SubstrateCS/Examples/Examples.sln @@ -0,0 +1,56 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C# Express 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Convert", "Convert\Convert.csproj", "{5BD42656-9BCF-4C55-8272-A5D3507EFDF3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatMap", "FlatMap\FlatMap.csproj", "{EDA894F2-00AF-456B-9D07-591ED61A9AE7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockReplace", "BlockReplace\BlockReplace.csproj", "{6D24D262-34D3-43A6-B066-1312A0C72B16}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GiveItem", "GiveItem\GiveItem.csproj", "{426B01F4-B0C0-488E-8A5A-5531C8DFA98C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoveSpawn", "MoveSpawn\MoveSpawn.csproj", "{15C04C0C-FD50-47E9-B62C-AA0A814189ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Skyscraper", "Skyscraper\Skyscraper.csproj", "{83F55F54-7253-4B4D-BC37-E9D1CB63E0B8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{B34A66B6-6A3B-42FC-AF39-74A30F487840}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5BD42656-9BCF-4C55-8272-A5D3507EFDF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BD42656-9BCF-4C55-8272-A5D3507EFDF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BD42656-9BCF-4C55-8272-A5D3507EFDF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BD42656-9BCF-4C55-8272-A5D3507EFDF3}.Release|Any CPU.Build.0 = Release|Any CPU + {EDA894F2-00AF-456B-9D07-591ED61A9AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDA894F2-00AF-456B-9D07-591ED61A9AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDA894F2-00AF-456B-9D07-591ED61A9AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDA894F2-00AF-456B-9D07-591ED61A9AE7}.Release|Any CPU.Build.0 = Release|Any CPU + {6D24D262-34D3-43A6-B066-1312A0C72B16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D24D262-34D3-43A6-B066-1312A0C72B16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D24D262-34D3-43A6-B066-1312A0C72B16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D24D262-34D3-43A6-B066-1312A0C72B16}.Release|Any CPU.Build.0 = Release|Any CPU + {426B01F4-B0C0-488E-8A5A-5531C8DFA98C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {426B01F4-B0C0-488E-8A5A-5531C8DFA98C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {426B01F4-B0C0-488E-8A5A-5531C8DFA98C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {426B01F4-B0C0-488E-8A5A-5531C8DFA98C}.Release|Any CPU.Build.0 = Release|Any CPU + {15C04C0C-FD50-47E9-B62C-AA0A814189ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15C04C0C-FD50-47E9-B62C-AA0A814189ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15C04C0C-FD50-47E9-B62C-AA0A814189ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15C04C0C-FD50-47E9-B62C-AA0A814189ED}.Release|Any CPU.Build.0 = Release|Any CPU + {83F55F54-7253-4B4D-BC37-E9D1CB63E0B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83F55F54-7253-4B4D-BC37-E9D1CB63E0B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83F55F54-7253-4B4D-BC37-E9D1CB63E0B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83F55F54-7253-4B4D-BC37-E9D1CB63E0B8}.Release|Any CPU.Build.0 = Release|Any CPU + {B34A66B6-6A3B-42FC-AF39-74A30F487840}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B34A66B6-6A3B-42FC-AF39-74A30F487840}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B34A66B6-6A3B-42FC-AF39-74A30F487840}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B34A66B6-6A3B-42FC-AF39-74A30F487840}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Substrate/SubstrateCS/Examples/FlatMap/FlatMap.csproj b/Substrate/SubstrateCS/Examples/FlatMap/FlatMap.csproj new file mode 100644 index 0000000..0466e04 --- /dev/null +++ b/Substrate/SubstrateCS/Examples/FlatMap/FlatMap.csproj @@ -0,0 +1,52 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {EDA894F2-00AF-456B-9D07-591ED61A9AE7} + Exe + Properties + FlatMap + FlatMap + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\bin\Release\Substrate.dll + + + + + + + + + + \ No newline at end of file diff --git a/Substrate/SubstrateCS/Examples/FlatMap/Program.cs b/Substrate/SubstrateCS/Examples/FlatMap/Program.cs new file mode 100644 index 0000000..e47978e --- /dev/null +++ b/Substrate/SubstrateCS/Examples/FlatMap/Program.cs @@ -0,0 +1,99 @@ +using System; +using Substrate; + +// 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) + { + string dest = "F:\\Minecraft\\test"; + int xmin = -10; + int xmax = 10; + int zmin = -10; + int zmaz = 10; + + // This will instantly create any necessary directory structure + BetaWorld world = BetaWorld.Create(dest); + ChunkManager cm = world.GetChunkManager(); + + // We can set different world parameters + world.Level.LevelName = "Flatlands"; + + // 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); + + // Auto light recalculation is horrifically bad for creating + // chunks from scratch, because we're placing thousands + // of blocks. Turn it off. + chunk.AutoRecalcLight = false; + + // Set the blocks + FlatChunk(chunk, 64); + + // Reset and rebuild the lighting for the entire chunk at once + chunk.RebuildBlockLight(); + chunk.RebuildSkyLight(); + + 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++) { + chunk.SetBlockID(x, y, z, (int)BlockType.BEDROCK); + } + } + } + + // Create stone + for (int y = 2; y < height - 5; y++) { + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + chunk.SetBlockID(x, y, z, (int)BlockType.STONE); + } + } + } + + // 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++) { + chunk.SetBlockID(x, y, z, (int)BlockType.DIRT); + } + } + } + + // Create grass + for (int y = height - 1; y < height; y++) { + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + chunk.SetBlockID(x, y, z, (int)BlockType.GRASS); + } + } + } + } + } +} diff --git a/Substrate/SubstrateCS/Examples/FlatMap/Properties/AssemblyInfo.cs b/Substrate/SubstrateCS/Examples/FlatMap/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..04d657b --- /dev/null +++ b/Substrate/SubstrateCS/Examples/FlatMap/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FlatMap")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("FlatMap")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("588c8d46-5ffb-4593-b48a-9529cf6fcede")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Substrate/SubstrateCS/Source/ChunkRef.cs b/Substrate/SubstrateCS/Source/ChunkRef.cs index 0da9817..bbd571e 100644 --- a/Substrate/SubstrateCS/Source/ChunkRef.cs +++ b/Substrate/SubstrateCS/Source/ChunkRef.cs @@ -19,6 +19,8 @@ namespace Substrate private bool _dirty; + private bool _autoLight = true; + public int X { get { return _container.ChunkGlobalX(_cx); } @@ -29,8 +31,6 @@ namespace Substrate get { return _container.ChunkGlobalZ(_cz); } } - - public int LocalX { get { return _container.ChunkLocalX(_cx); } @@ -41,6 +41,12 @@ namespace Substrate get { return _container.ChunkLocalZ(_cz); } } + public bool AutoRecalcLight + { + get { return _autoLight; } + set { _autoLight = value; } + } + public ChunkRef (IChunkContainer container, IChunkCache cache, int cx, int cz) { _container = container; @@ -268,14 +274,16 @@ namespace Substrate if (GetChunk().SetBlockID(lx, ly, lz, id)) { MarkDirty(); - BlockInfo info2 = GetChunk().GetBlockInfo(lx, ly, lz); - if (info1.Luminance != info2.Luminance || info1.Opacity != info2.Opacity) { - UpdateBlockLight(lx, ly, lz); - } + if (_autoLight) { + BlockInfo info2 = GetChunk().GetBlockInfo(lx, ly, lz); + if (info1.Luminance != info2.Luminance || info1.Opacity != info2.Opacity) { + UpdateBlockLight(lx, ly, lz); + } - if (info1.Opacity != info2.Opacity) { - _update.Enqueue(new BlockKey(lx, ly, lz)); - UpdateSkyLight(); + if (info1.Opacity != info2.Opacity) { + _update.Enqueue(new BlockKey(lx, ly, lz)); + UpdateSkyLight(); + } } return true; @@ -430,6 +438,48 @@ namespace Substrate private BitArray _lightbit; private Queue _update; + public void RebuildBlockLight () + { + for (int x = 0; x < XDim; x++) { + for (int z = 0; z < ZDim; z++) { + for (int y = 0; y < YDim; y++) { + BlockInfo info = GetBlockInfo(x, y, z); + if (info == null || info.Luminance == 0) { + SetBlockLight(x, y, z, 0); + } + else { + SetBlockLight(x, y, z, Math.Max(info.Luminance - info.Opacity, 0)); + QueueRelight(new BlockKey(x, y, z)); + } + } + } + } + + UpdateBlockLight(); + } + + public void RebuildSkyLight () + { + for (int x = 0; x < XDim; x++) { + for (int z = 0; z < ZDim; z++) { + int height = GetHeight(x, z); + for (int y = 0; y < YDim; y++) { + if (y > height) { + SetBlockLight(x, y, z, BlockInfo.MAX_LUMINANCE); + } + else if (y < height) { + SetBlockLight(x, y, z, 0); + } + else { + QueueRelight(new BlockKey(x, y, z)); + } + } + } + } + + UpdateSkyLight(); + } + private void UpdateBlockLight (int lx, int ly, int lz) { BlockKey primary = new BlockKey(lx, ly, lz); @@ -442,6 +492,11 @@ namespace Substrate QueueRelight(new BlockKey(lx, ly, lz - 1)); QueueRelight(new BlockKey(lx, ly, lz + 1)); + UpdateBlockLight(); + } + + private void UpdateBlockLight () + { while (_update.Count > 0) { BlockKey k = _update.Dequeue(); int index = LightBitmapIndex(k); diff --git a/Substrate/SubstrateCS/Source/World.cs b/Substrate/SubstrateCS/Source/World.cs index d02e14f..7dbe9ba 100644 --- a/Substrate/SubstrateCS/Source/World.cs +++ b/Substrate/SubstrateCS/Source/World.cs @@ -17,6 +17,8 @@ namespace Substrate { string WorldPath { get; } + Level Level { get; } + IBlockManager GetBlockManager (); IBlockManager GetBlockManager (int dim); @@ -171,6 +173,11 @@ namespace Substrate get { return _path; } } + public Level Level + { + get { return _level; } + } + IBlockManager INBTWorld.GetBlockManager () { return GetBlockManager(); @@ -370,6 +377,11 @@ namespace Substrate get { return _path; } } + public Level Level + { + get { return _level; } + } + IBlockManager INBTWorld.GetBlockManager () { return GetBlockManager();