diff --git a/Substrate/SubstrateCS/Examples/BlockReplace/BlockReplace.csproj b/Substrate/SubstrateCS/Examples/BlockReplace/BlockReplace.csproj
new file mode 100644
index 0000000..4df719a
--- /dev/null
+++ b/Substrate/SubstrateCS/Examples/BlockReplace/BlockReplace.csproj
@@ -0,0 +1,56 @@
+
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {6D24D262-34D3-43A6-B066-1312A0C72B16}
+ Exe
+ Properties
+ BlockReplace
+ BlockReplace
+ v4.0
+ 512
+
+
+
+
+ 3.5
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\bin\Release\Substrate.dll
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Substrate/SubstrateCS/Examples/BlockReplace/Program.cs b/Substrate/SubstrateCS/Examples/BlockReplace/Program.cs
new file mode 100644
index 0000000..c106e8c
--- /dev/null
+++ b/Substrate/SubstrateCS/Examples/BlockReplace/Program.cs
@@ -0,0 +1,61 @@
+using System;
+using Substrate;
+
+// This example replaces all instances of one block ID with another in a world.
+// Substrate will handle all of the lower-level headaches that can pop up, such
+// as maintaining correct lighting or replacing TileEntity records for blocks
+// that need them.
+
+// For a more advanced Block Replace example, see replace.cs in NBToolkit.
+
+namespace BlockReplace
+{
+ class Program
+ {
+ static void Main (string[] args)
+ {
+ if (args.Length != 3) {
+ Console.WriteLine("Usage: BlockReplace ");
+ return;
+ }
+
+ string dest = args[0];
+ int before = Convert.ToInt32(args[1]);
+ int after = Convert.ToInt32(args[2]);
+
+ // Open our world
+ BetaWorld world = BetaWorld.Open(dest);
+
+ // The chunk manager is more efficient than the block manager for
+ // this purpose, since we'll inspect every block
+ ChunkManager cm = world.GetChunkManager();
+
+ foreach (ChunkRef chunk in cm) {
+ // You could hardcode your dimensions, but maybe some day they
+ // won't always be 16. Also the CLR is a bit stupid and has
+ // trouble optimizing repeated calls to Chunk.Blocks.xx, so we
+ // cache them in locals
+ int xdim = chunk.Blocks.XDim;
+ int ydim = chunk.Blocks.YDim;
+ int zdim = chunk.Blocks.ZDim;
+
+ // x, z, y is the most efficient order to scan blocks (not that
+ // you should care about internal detail)
+ for (int x = 0; x < xdim; x++) {
+ for (int z = 0; z < zdim; z++) {
+ for (int y = 0; y < ydim; y++) {
+
+ // Replace the block with after if it matches before
+ if (chunk.Blocks.GetID(x, y, z) == before) {
+ chunk.Blocks.SetID(x, y, z, after);
+ }
+ }
+ }
+ }
+
+ // Save the chunk
+ cm.Save();
+ }
+ }
+ }
+}
diff --git a/Substrate/SubstrateCS/Examples/BlockReplace/Properties/AssemblyInfo.cs b/Substrate/SubstrateCS/Examples/BlockReplace/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..3cf8e7a
--- /dev/null
+++ b/Substrate/SubstrateCS/Examples/BlockReplace/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("BlockReplace")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("BlockReplace")]
+[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("672d767f-c56e-42eb-8583-a835bcf7d4a0")]
+
+// 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/Examples/FlatMap/Program.cs b/Substrate/SubstrateCS/Examples/FlatMap/Program.cs
index 70f816f..572b60b 100644
--- a/Substrate/SubstrateCS/Examples/FlatMap/Program.cs
+++ b/Substrate/SubstrateCS/Examples/FlatMap/Program.cs
@@ -27,7 +27,10 @@ namespace FlatMap
world.Level.SpawnX = 20;
world.Level.SpawnZ = 20;
world.Level.SpawnY = 70;
- //world.Level.SetDefaultPlayer();
+
+ // 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.
// We'll create chunks at chunk coordinates xmin,zmin to xmax,zmax
for (int xi = xmin; xi < xmax; xi++) {
diff --git a/Substrate/SubstrateCS/Examples/MoveSpawn/Program.cs b/Substrate/SubstrateCS/Examples/MoveSpawn/Program.cs
index 01a7e76..5f5ea5e 100644
--- a/Substrate/SubstrateCS/Examples/MoveSpawn/Program.cs
+++ b/Substrate/SubstrateCS/Examples/MoveSpawn/Program.cs
@@ -1,10 +1,9 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
using Substrate;
+// MoveSpawn changes the location of the world spawn location
+// (which is separate from individual player spawn locations)
+
namespace MoveSpawn
{
class Program
@@ -21,12 +20,18 @@ namespace MoveSpawn
int y = Convert.ToInt32(args[2]);
int z = Convert.ToInt32(args[3]);
+ // Open our world
BetaWorld world = BetaWorld.Open(dest);
+ // Set the level's spawn
+ // Note: Players do not have separate spawns by default
+ // If you wanted to change a player's spawn, you must set all
+ // 3 coordinates for it to stick. It will not take the level's defaults.
world.Level.SpawnX = x;
world.Level.SpawnY = y;
world.Level.SpawnZ = z;
+ // Save the changes
world.Save();
}
}
diff --git a/Substrate/SubstrateCS/Examples/PurgeEntities/Program.cs b/Substrate/SubstrateCS/Examples/PurgeEntities/Program.cs
index 59b8c66..f53e0b6 100644
--- a/Substrate/SubstrateCS/Examples/PurgeEntities/Program.cs
+++ b/Substrate/SubstrateCS/Examples/PurgeEntities/Program.cs
@@ -2,6 +2,10 @@
using System.Collections.Generic;
using Substrate;
+// This example is a tool to delete all entities of a given type (e.g., "pig")
+// on a map. It optionally can be restricted to boxed region in block coords.
+// Only 10% of the effort is actually spend purging anything.
+
namespace PurgeEntities
{
class Program
@@ -16,11 +20,13 @@ namespace PurgeEntities
string dest = args[0];
string eid = args[1];
+ // Our initial bounding box is "infinite"
int x1 = BlockManager.MIN_X;
int x2 = BlockManager.MAX_X;
int z1 = BlockManager.MIN_Z;
int z2 = BlockManager.MAX_Z;
+ // If we have all coordinate parameters, set the bounding box
if (args.Length == 6) {
x1 = Convert.ToInt32(args[2]);
z1 = Convert.ToInt32(args[3]);
diff --git a/Substrate/SubstrateCS/Examples/Relight/Program.cs b/Substrate/SubstrateCS/Examples/Relight/Program.cs
index b781e87..23f47bd 100644
--- a/Substrate/SubstrateCS/Examples/Relight/Program.cs
+++ b/Substrate/SubstrateCS/Examples/Relight/Program.cs
@@ -1,6 +1,16 @@
using System;
using Substrate;
+// This example will reset and rebuild the lighting (heightmap, block light,
+// skylight) for all chunks in a map.
+
+// Note: If it looks silly to reset the lighting, loading and saving
+// all the chunks, just to load and save them again later: it's not.
+// If the world lighting is not correct, it must be completely reset
+// before rebuilding the light in any chunks. That's just how the
+// algorithms work, in order to limit the number of chunks that must
+// be loaded at any given time.
+
namespace Relight
{
class Program