diff --git a/NBToolkit/BlockFilter.cs b/NBToolkit/BlockFilter.cs index 8db6423..808e567 100644 --- a/NBToolkit/BlockFilter.cs +++ b/NBToolkit/BlockFilter.cs @@ -28,6 +28,9 @@ namespace NBToolkit int ExcludedBlockCount { get; } double? ProbMatch { get; } + + bool IncludedBlocksContains (int id); + bool ExcludedBlocksContains (int id); } public class BlockFilter : IOptions, IBlockFilter @@ -51,11 +54,13 @@ namespace NBToolkit public int? XAboveEq { get { return _xAboveEq; } + set { _xAboveEq = value; } } public int? XBelowEq { get { return _xBelowEq; } + set { _xBelowEq = value; } } public int? YAboveEq @@ -130,8 +135,24 @@ namespace NBToolkit v => _invertXYZ = true }, { "bi|BlockInclude=", "Match blocks of type {ID}. This option is repeatable.", v => _includedBlocks.Add(Convert.ToInt32(v) % 256) }, + { "bir|BlockIncludeRange=", "Match blocks of type between {0:V1} and {1:V2}, inclusive. This option is repeatable.", + (v1, v2) => { + int i1 = Math.Max(0, Math.Min(255, Convert.ToInt32(v1))); + int i2 = Math.Max(0, Math.Min(255, Convert.ToInt32(v2))); + for (int i = i1; i <= i2; i++) { + _includedBlocks.Add(i); + } + } }, { "bx|BlockExclude=", "Match all blocks except blocks of type {ID}. This option is repeatable.", v => _excludedBlocks.Add(Convert.ToInt32(v) % 256) }, + { "ber|BlockExcludeRange=", "Match all blocks except blocks of type between {0:V1} and {1:V2}, inclusive. This option is repeatable.", + (v1, v2) => { + int i1 = Math.Max(0, Math.Min(255, Convert.ToInt32(v1))); + int i2 = Math.Max(0, Math.Min(255, Convert.ToInt32(v2))); + for (int i = i1; i <= i2; i++) { + _excludedBlocks.Add(i); + } + } }, { "bp|BlockProbability=", "Selects a matching block with probability {VAL} (0.0-1.0)", v => _prob = Convert.ToDouble(v) }, }; @@ -153,5 +174,15 @@ namespace NBToolkit Console.WriteLine("Block Filtering Options:"); _options.WriteOptionDescriptions(Console.Out); } + + public bool IncludedBlocksContains (int id) + { + return _includedBlocks.Contains(id); + } + + public bool ExcludedBlocksContains (int id) + { + return _excludedBlocks.Contains(id); + } } } diff --git a/NBToolkit/ChunkFilter.cs b/NBToolkit/ChunkFilter.cs index c832f3a..4d0bd7d 100644 --- a/NBToolkit/ChunkFilter.cs +++ b/NBToolkit/ChunkFilter.cs @@ -31,6 +31,9 @@ namespace NBToolkit bool ExcludeMatchAll { get; } double? ProbMatch { get; } + + bool IncludedBlocksContains (int id); + bool ExcludedBlocksContains (int id); } public class ChunkFilter : IOptions, IChunkFilter @@ -55,21 +58,25 @@ namespace NBToolkit public int? XAboveEq { get { return _xAboveEq; } + set { _xAboveEq = value; } } public int? XBelowEq { get { return _xBelowEq; } + set { _xBelowEq = value; } } public int? ZAboveEq { get { return _zAboveEq; } + set { _zAboveEq = value; } } public int? ZBelowEq { get { return _zBelowEq; } + set { _zBelowEq = value; } } public bool InvertXZ @@ -167,5 +174,15 @@ namespace NBToolkit Console.WriteLine("Chunk Filtering Options:"); _options.WriteOptionDescriptions(Console.Out); } + + public bool IncludedBlocksContains (int id) + { + return _includedBlocks.Contains(id); + } + + public bool ExcludedBlocksContains (int id) + { + return _excludedBlocks.Contains(id); + } } } diff --git a/NBToolkit/Dump.cs b/NBToolkit/Dump.cs index 3190f6b..1d7f8a1 100644 --- a/NBToolkit/Dump.cs +++ b/NBToolkit/Dump.cs @@ -4,7 +4,8 @@ using System.Text; using System.IO; using NDesk.Options; using Substrate; -using Substrate.NBT; +using Substrate.Nbt; +using Substrate.Core; namespace NBToolkit { @@ -96,7 +97,7 @@ namespace NBToolkit public override void Run () { - INBTWorld world = GetWorld(opt); + NbtWorld world = GetWorld(opt); IChunkManager cm = world.GetChunkManager(opt.OPT_DIM); FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter()); diff --git a/NBToolkit/FilteredChunkManager.cs b/NBToolkit/FilteredChunkManager.cs index b6169b1..99ba058 100644 --- a/NBToolkit/FilteredChunkManager.cs +++ b/NBToolkit/FilteredChunkManager.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.Text; using Substrate; +using Substrate.Core; namespace NBToolkit { @@ -230,5 +231,15 @@ namespace NBToolkit } #endregion + + #region IChunkContainer Members + + + public bool CanDelegateCoordinates + { + get { return false; } + } + + #endregion } } diff --git a/NBToolkit/GenOres.cs b/NBToolkit/GenOres.cs index 18681f7..51727d7 100644 --- a/NBToolkit/GenOres.cs +++ b/NBToolkit/GenOres.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using Substrate; +using Substrate.Core; namespace NBToolkit { @@ -100,8 +101,8 @@ namespace NBToolkit for (int iz = zStart; iz <= zEnd; iz++) { double zThresh = (iz + 0.5D - zPos) / (fuzzXZ / 2.0D); if (xThresh * xThresh + yThresh * yThresh + zThresh * zThresh < 1.0D) { - BlockRef block = blockMan.GetBlockRef(ix, iy, iz); - if (block != null) { + AlphaBlockRef block = blockMan.GetBlockRef(ix, iy, iz); + if (block.IsValid) { block.ID = _blockId; block.Data = _blockData; } diff --git a/NBToolkit/Oregen.cs b/NBToolkit/Oregen.cs index b632298..56b91a8 100644 --- a/NBToolkit/Oregen.cs +++ b/NBToolkit/Oregen.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using NDesk.Options; using Substrate; +using Substrate.Core; namespace NBToolkit { @@ -181,7 +182,7 @@ namespace NBToolkit public override void Run () { - INBTWorld world = GetWorld(opt); + NbtWorld world = GetWorld(opt); IChunkManager cm = world.GetChunkManager(opt.OPT_DIM); FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter()); @@ -205,7 +206,7 @@ namespace NBToolkit Console.WriteLine("Affected Chunks: " + affectedChunks); } - public void ApplyChunk (INBTWorld world, ChunkRef chunk) + public void ApplyChunk (NbtWorld world, ChunkRef chunk) { if (opt.OPT_V) { Console.WriteLine("Generating {0} size {1} deposits of {2} between {3} and {4}", @@ -265,7 +266,7 @@ namespace NBToolkit return false; } - int blockID = _cache.Blocks.GetID(x & _chunkXMask, y & _chunkYMask, z & _chunkZMask); + int blockID = cache.Blocks.GetID(x & chunkXMask, y & chunkYMask, z & chunkZMask); if ( ((opt.OPT_OA) && (blockID != opt.OPT_ID)) || diff --git a/NBToolkit/Purge.cs b/NBToolkit/Purge.cs index 79df1e6..f73a3c9 100644 --- a/NBToolkit/Purge.cs +++ b/NBToolkit/Purge.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using NDesk.Options; using Substrate; +using Substrate.Core; namespace NBToolkit { @@ -69,7 +70,7 @@ namespace NBToolkit public override void Run () { - INBTWorld world = GetWorld(opt); + NbtWorld world = GetWorld(opt); IChunkManager cm = world.GetChunkManager(opt.OPT_DIM); FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter()); diff --git a/NBToolkit/Relight.cs b/NBToolkit/Relight.cs index 5bf5dcc..c4835c3 100644 --- a/NBToolkit/Relight.cs +++ b/NBToolkit/Relight.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using NDesk.Options; using Substrate; +using Substrate.Core; namespace NBToolkit { @@ -11,9 +12,9 @@ namespace NBToolkit private OptionSet _filterOpt = null; private ChunkFilter _chunkFilter = null; - public bool BlockLight; - public bool SkyLight; - public bool HeightMap; + public bool BlockLight = false; + public bool SkyLight = false; + public bool HeightMap = false; public RelightOptions () : base() @@ -82,7 +83,7 @@ namespace NBToolkit public override void Run () { - INBTWorld world = GetWorld(opt); + NbtWorld world = GetWorld(opt); IChunkManager cm = world.GetChunkManager(opt.OPT_DIM); FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter()); diff --git a/NBToolkit/Replace.cs b/NBToolkit/Replace.cs index 327f300..dc1aa85 100644 --- a/NBToolkit/Replace.cs +++ b/NBToolkit/Replace.cs @@ -4,6 +4,7 @@ using System.Text; using System.Globalization; using NDesk.Options; using Substrate; +using Substrate.Core; namespace NBToolkit { @@ -134,6 +135,23 @@ namespace NBToolkit throw new TKOptionException(); } + + if (_blockFilter.XAboveEq != null) { + int cx = (int)_blockFilter.XAboveEq >> 5; + _chunkFilter.XAboveEq = Math.Max(_chunkFilter.XAboveEq ?? cx, cx); + } + if (_blockFilter.XBelowEq != null) { + int cx = (int)_blockFilter.XBelowEq >> 5; + _chunkFilter.XBelowEq = Math.Min(_chunkFilter.XBelowEq ?? cx, cx); + } + if (_blockFilter.ZAboveEq != null) { + int cx = (int)_blockFilter.ZAboveEq >> 5; + _chunkFilter.ZAboveEq = Math.Max(_chunkFilter.ZAboveEq ?? cx, cx); + } + if (_blockFilter.ZBelowEq != null) { + int cx = (int)_blockFilter.ZBelowEq >> 5; + _chunkFilter.ZBelowEq = Math.Min(_chunkFilter.ZBelowEq ?? cx, cx); + } } public IChunkFilter GetChunkFilter () @@ -153,30 +171,38 @@ namespace NBToolkit private static Random rand = new Random(); + private List[] _sort = new List[256]; + public Replace (ReplaceOptions o) { opt = o; + + for (int i = 0; i < 256; i++) { + _sort[i] = new List(); + } } public override void Run () { - INBTWorld world = GetWorld(opt); + NbtWorld world = GetWorld(opt); IChunkManager cm = world.GetChunkManager(opt.OPT_DIM); FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter()); int affectedChunks = 0; foreach (ChunkRef chunk in fcm) { - affectedChunks++; + if (opt.OPT_V) { + Console.WriteLine("Processing chunk {0},{1}...", chunk.X, chunk.Z); + } ApplyChunk(world, chunk); - fcm.Save(); + affectedChunks += fcm.Save() > 0 ? 1 : 0; } Console.WriteLine("Affected Chunks: " + affectedChunks); } - public void ApplyChunk (INBTWorld world, ChunkRef chunk) + public void ApplyChunk (NbtWorld world, ChunkRef chunk) { IBlockFilter opt_b = opt.GetBlockFilter(); @@ -195,7 +221,7 @@ namespace NBToolkit } xmin = (xmin < 0) ? 0 : xmin; - xmax = (xmin > 15) ? 15 : xmax; + xmax = (xmax > 15) ? 15 : xmax; if (xmin > 15 || xmax < 0 || xmin > xmax) { return; @@ -228,7 +254,7 @@ namespace NBToolkit } zmin = (zmin < 0) ? 0 : zmin; - zmax = (zmin > 15) ? 15 : zmax; + zmax = (zmax > 15) ? 15 : zmax; if (zmin > 15 || zmax < 0 || zmin > zmax) { return; @@ -238,8 +264,52 @@ namespace NBToolkit int ydim = chunk.Blocks.YDim; int zdim = chunk.Blocks.ZDim; - // Process Chunk + // Bin blocks for (int y = ymin; y <= ymax; y++) { + for (int x = xmin; x <= xmax; x++) { + for (int z = zmin; z <= zmax; z++) { + int id = chunk.Blocks.GetID(x, y, z); + _sort[id].Add(new BlockKey(x, y, z)); + } + } + } + + // Process bins + for (int i = 0; i < 256; i++) { + if (_sort[i].Count == 0) { + continue; + } + + if (opt_b.IncludedBlockCount > 0 & !opt_b.IncludedBlocksContains(i)) { + continue; + } + + if (opt_b.ExcludedBlockCount > 0 & opt_b.ExcludedBlocksContains(i)) { + continue; + } + + foreach (BlockKey key in _sort[i]) { + chunk.Blocks.SetID(key.x, key.y, key.z, (int)opt.OPT_AFTER); + + if (opt.OPT_VV) { + int gx = chunk.X * xdim + key.x; + int gz = chunk.Z * zdim + key.z; + Console.WriteLine("Replaced block {0} at {1},{2},{3}", i, gx, key.y, gz); + } + + if (opt.OPT_DATA != null) { + chunk.Blocks.SetData(key.x, key.y, key.z, (int)opt.OPT_DATA); + } + } + } + + // Reset bins + for (int i = 0; i < 256; i++) { + _sort[i].Clear(); + } + + // Process Chunk + /*for (int y = ymin; y <= ymax; y++) { for (int x = xmin; x <= xmax; x++) { for (int z = zmin; z <= zmax; z++) { // Probability test @@ -301,7 +371,7 @@ namespace NBToolkit } } } - } + }*/ } } } diff --git a/NBToolkit/TKFilter.cs b/NBToolkit/TKFilter.cs index 41a5775..2de1a21 100644 --- a/NBToolkit/TKFilter.cs +++ b/NBToolkit/TKFilter.cs @@ -11,9 +11,9 @@ namespace NBToolkit public abstract void Run (); - public INBTWorld GetWorld (TKOptions opt) + public NbtWorld GetWorld (TKOptions opt) { - INBTWorld world = null; + NbtWorld world = null; try { if (opt.OPT_ALPHA) { world = AlphaWorld.Open(opt.OPT_WORLD);