ChunkRef enumerators moved into Manager class namespaces; Manager classes now offer enumerators directly.

This commit is contained in:
Justin Aquadro 2011-04-08 20:52:28 +00:00
parent f1c79f6312
commit 0cf047c51d
15 changed files with 245 additions and 422 deletions

View file

@ -97,7 +97,9 @@ namespace NBToolkit
public override void Run () public override void Run ()
{ {
World world = new World(opt.OPT_WORLD); World world = new World(opt.OPT_WORLD);
ChunkManager cm = world.GetChunkManager() as ChunkManager; ChunkManager cm = world.GetChunkManager() as ChunkManager;
FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter());
StreamWriter fstr; StreamWriter fstr;
try { try {
@ -111,7 +113,7 @@ namespace NBToolkit
fstr.WriteLine("["); fstr.WriteLine("[");
bool first = true; bool first = true;
foreach (ChunkRef chunk in new FilteredChunkList(cm, opt.GetChunkFilter())) { foreach (ChunkRef chunk in fcm) {
if (!first) { if (!first) {
fstr.Write(","); fstr.Write(",");
} }

View file

@ -1,116 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using Substrate;
namespace NBToolkit
{
public class FilteredChunkList : ChunkList
{
protected IChunkFilter _filter;
public FilteredChunkList (ChunkManager cm, IChunkFilter filter)
: base(cm)
{
_filter = filter;
}
public FilteredChunkList (ChunkManager cm, Region reg, IChunkFilter filter)
: base(cm, reg)
{
_filter = filter;
}
public override ChunkEnumerator GetEnumerator ()
{
return new FilteredChunkEnumerator(_cm, _region, _filter);
}
}
public class FilteredChunkEnumerator : ChunkEnumerator
{
protected IChunkFilter _filter;
public FilteredChunkEnumerator (ChunkManager cm, IChunkFilter filter)
: base(cm)
{
_filter = filter;
}
public FilteredChunkEnumerator (ChunkManager cm, Region reg, IChunkFilter filter)
: base(cm, reg)
{
_filter = filter;
}
public override bool MoveNext ()
{
while (true) {
if (base.MoveNext() == false) {
return false;
}
// Filter by coordinates
if (_filter.InvertXZ) {
if (_filter.XAboveEq != null && _filter.XBelowEq != null &&
_filter.ZAboveEq != null && _filter.ZBelowEq != null &&
Current.X >= _filter.XAboveEq && Current.X <= _filter.XBelowEq &&
Current.Z >= _filter.ZAboveEq && Current.Z <= _filter.ZBelowEq) {
continue;
}
}
else {
if (_filter.XAboveEq != null && Current.X < _filter.XAboveEq) {
continue;
}
if (_filter.XBelowEq != null && Current.X > _filter.XBelowEq) {
continue;
}
if (_filter.ZAboveEq != null && Current.Z < _filter.ZAboveEq) {
continue;
}
if (_filter.ZBelowEq != null && Current.Z > _filter.ZBelowEq) {
continue;
}
}
// Filter out chunks that do not contain required blocks (included list)
if (_filter.IncludedBlockCount > 0) {
int matchCount = 0;
foreach (int block in _filter.IncludedBlocks) {
if (Current.CountBlockID(block) > 0) {
matchCount++;
}
}
if (_filter.IncludeMatchAny && matchCount == 0) {
continue;
}
if (_filter.IncludeMatchAll && matchCount != _filter.IncludedBlockCount) {
continue;
}
}
// Filter out chunks that contain forbiddon blocks (excluded list)
if (_filter.ExcludedBlockCount > 0) {
int matchCount = 0;
foreach (int block in _filter.ExcludedBlocks) {
if (Current.CountBlockID(block) > 0) {
matchCount++;
}
}
if (_filter.ExcludeMatchAny && matchCount > 0) {
continue;
}
if (_filter.ExcludeMatchAll && matchCount == _filter.ExcludedBlockCount) {
continue;
}
}
return true;
}
}
}
}

View file

@ -54,11 +54,12 @@
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Dump.cs" /> <Compile Include="Dump.cs" />
<Compile Include="ChunkFilter.cs" /> <Compile Include="ChunkFilter.cs" />
<Compile Include="FilteredChunkEnumerator.cs" /> <Compile Include="FilteredChunkManager.cs" />
<Compile Include="GenOres.cs" /> <Compile Include="GenOres.cs" />
<Compile Include="MathHelper.cs" /> <Compile Include="MathHelper.cs" />
<Compile Include="NDesk\Options.cs" /> <Compile Include="NDesk\Options.cs" />

View file

@ -182,10 +182,12 @@ namespace NBToolkit
public override void Run () public override void Run ()
{ {
World world = new World(opt.OPT_WORLD); World world = new World(opt.OPT_WORLD);
ChunkManager cm = world.GetChunkManager() as ChunkManager; ChunkManager cm = world.GetChunkManager() as ChunkManager;
FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter());
int affectedChunks = 0; int affectedChunks = 0;
foreach (ChunkRef chunk in new FilteredChunkList(cm, opt.GetChunkFilter())) { foreach (ChunkRef chunk in fcm) {
if (chunk == null || !chunk.IsTerrainPopulated) { if (chunk == null || !chunk.IsTerrainPopulated) {
continue; continue;
} }

View file

@ -72,9 +72,10 @@ namespace NBToolkit
World world = new World(opt.OPT_WORLD); World world = new World(opt.OPT_WORLD);
ChunkManager cm = world.GetChunkManager() as ChunkManager; ChunkManager cm = world.GetChunkManager() as ChunkManager;
FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter());
int affectedChunks = 0; int affectedChunks = 0;
foreach (ChunkRef chunk in new FilteredChunkList(cm, opt.GetChunkFilter())) { foreach (ChunkRef chunk in fcm) {
affectedChunks++; affectedChunks++;
world.GetChunkManager().DeleteChunk(chunk.X, chunk.Z); world.GetChunkManager().DeleteChunk(chunk.X, chunk.Z);
} }

View file

@ -152,8 +152,10 @@ namespace NBToolkit
World world = new World(opt.OPT_WORLD); World world = new World(opt.OPT_WORLD);
ChunkManager cm = world.GetChunkManager() as ChunkManager; ChunkManager cm = world.GetChunkManager() as ChunkManager;
FilteredChunkManager fcm = new FilteredChunkManager(cm, opt.GetChunkFilter());
int affectedChunks = 0; int affectedChunks = 0;
foreach (ChunkRef chunk in new FilteredChunkList(cm, opt.GetChunkFilter())) { foreach (ChunkRef chunk in fcm) {
affectedChunks++; affectedChunks++;
ApplyChunk(world, chunk); ApplyChunk(world, chunk);

View file

@ -73,7 +73,7 @@ namespace NBToolkit
throw new TKOptionException(); throw new TKOptionException();
} }
if (!File.Exists(Path.Combine(OPT_WORLD, "level.dat"))) { /*if (!File.Exists(Path.Combine(OPT_WORLD, "level.dat"))) {
Console.WriteLine("Error: The supplied world path is invalid"); Console.WriteLine("Error: The supplied world path is invalid");
Console.WriteLine(); Console.WriteLine();
this.PrintUsage(); this.PrintUsage();
@ -87,7 +87,7 @@ namespace NBToolkit
this.PrintUsage(); this.PrintUsage();
throw new TKOptionException(); throw new TKOptionException();
} }*/
} }
} }

View file

@ -1,156 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
namespace Substrate
{
public class ChunkList : IEnumerable<ChunkRef>
{
//private List<Region> _regions;
protected ChunkManager _cm = null;
protected Region _region = null;
// Constructor to enumerate a single region
public ChunkList (ChunkManager cm, Region region)
{
_cm = cm;
_region = region;
}
// Constructor to enumerate all regions
public ChunkList (ChunkManager cm)
{
_cm = cm;
}
IEnumerator IEnumerable.GetEnumerator ()
{
return (IEnumerator)GetEnumerator();
}
IEnumerator<ChunkRef> IEnumerable<ChunkRef>.GetEnumerator ()
{
return (IEnumerator<ChunkRef>)GetEnumerator();
}
public virtual ChunkEnumerator GetEnumerator ()
{
return new ChunkEnumerator(_cm, _region);
}
}
public class ChunkEnumerator : IEnumerator<ChunkRef>
{
protected Region _region;
protected ChunkManager _cm;
protected ChunkRef _chunk;
protected RegionEnumerator _enum = null;
protected int _x = 0;
protected int _z = -1;
public ChunkEnumerator (ChunkManager cm, Region region)
{
_cm = cm;
_region = region;
if (_region == null) {
_enum = new RegionEnumerator(_cm.GetRegionManager());
_enum.MoveNext();
_region = _enum.Current;
}
}
public ChunkEnumerator (ChunkManager cm)
{
_cm = cm;
_enum = new RegionEnumerator(_cm.GetRegionManager());
_enum.MoveNext();
_region = _enum.Current;
}
public virtual bool MoveNext ()
{
if (_enum == null) {
return MoveNextInRegion();
}
else {
while (true) {
if (_x >= ChunkManager.REGION_XLEN) {
if (!_enum.MoveNext()) {
return false;
}
_x = 0;
_z = -1;
_region = _enum.Current;
}
if (MoveNextInRegion()) {
_chunk = _cm.GetChunkRefInRegion(_region, _x, _z);
return true;
}
}
}
}
protected bool MoveNextInRegion ()
{
for (; _x < ChunkManager.REGION_XLEN; _x++) {
for (_z++; _z < ChunkManager.REGION_ZLEN; _z++) {
if (_region.ChunkExists(_x, _z)) {
goto FoundNext;
}
}
_z = -1;
}
FoundNext:
return (_x < ChunkManager.REGION_XLEN);
}
public void Reset ()
{
if (_enum != null) {
_enum.Reset();
_enum.MoveNext();
_region = _enum.Current;
}
_x = 0;
_z = -1;
}
void IDisposable.Dispose () { }
object IEnumerator.Current
{
get
{
return Current;
}
}
ChunkRef IEnumerator<ChunkRef>.Current
{
get
{
return Current;
}
}
public ChunkRef Current
{
get
{
if (_x >= ChunkManager.REGION_XLEN) {
throw new InvalidOperationException();
}
return _chunk;
}
}
}
}

View file

@ -184,5 +184,23 @@ namespace Substrate
#endregion #endregion
#region IEnumerable<ChunkRef> Members
public IEnumerator<ChunkRef> GetEnumerator ()
{
return null;
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
{
return null;
}
#endregion
} }
} }

View file

@ -48,7 +48,7 @@ namespace Substrate
bool SaveChunk (Chunk chunk); bool SaveChunk (Chunk chunk);
} }
public interface IChunkManager : IChunkContainer public interface IChunkManager : IChunkContainer, IEnumerable<ChunkRef>
{ {
} }

View file

@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Collections;
namespace Substrate namespace Substrate
{ {
@ -28,6 +28,13 @@ namespace Substrate
_dirty = new Dictionary<RegionKey, Region>(); _dirty = new Dictionary<RegionKey, Region>();
} }
public ChunkManager (ChunkManager cm)
{
_regionMan = cm._regionMan;
_cache = new Dictionary<RegionKey, Region>();
_dirty = new Dictionary<RegionKey, Region>();
}
public int ChunkGlobalX (int cx) public int ChunkGlobalX (int cx)
{ {
return cx; return cx;
@ -170,6 +177,7 @@ namespace Substrate
return _regionMan.GetRegion(cx, cz); return _regionMan.GetRegion(cx, cz);
} }
#region IEnumerable<ChunkRef> Members #region IEnumerable<ChunkRef> Members
public IEnumerator<ChunkRef> GetEnumerator () public IEnumerator<ChunkRef> GetEnumerator ()
@ -179,6 +187,7 @@ namespace Substrate
#endregion #endregion
#region IEnumerable Members #region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
@ -187,6 +196,108 @@ namespace Substrate
} }
#endregion #endregion
public class ChunkEnumerator : IEnumerator<ChunkRef>
{
private ChunkManager _cm;
private IEnumerator<Region> _enum;
private Region _region;
private ChunkRef _chunk;
private int _x = 0;
private int _z = -1;
//protected RegionEnumerator _enum = null;
public ChunkEnumerator (ChunkManager cm)
{
_cm = cm;
_enum = _cm.GetRegionManager().GetEnumerator();
_enum.MoveNext();
_region = _enum.Current;
}
public virtual bool MoveNext ()
{
if (_enum == null) {
return MoveNextInRegion();
}
else {
while (true) {
if (_x >= ChunkManager.REGION_XLEN) {
if (!_enum.MoveNext()) {
return false;
}
_x = 0;
_z = -1;
_region = _enum.Current;
}
if (MoveNextInRegion()) {
_chunk = _cm.GetChunkRefInRegion(_region, _x, _z);
return true;
}
}
}
}
protected bool MoveNextInRegion ()
{
for (; _x < ChunkManager.REGION_XLEN; _x++) {
for (_z++; _z < ChunkManager.REGION_ZLEN; _z++) {
if (_region.ChunkExists(_x, _z)) {
goto FoundNext;
}
}
_z = -1;
}
FoundNext:
return (_x < ChunkManager.REGION_XLEN);
}
public void Reset ()
{
if (_enum != null) {
_enum.Reset();
_enum.MoveNext();
_region = _enum.Current;
}
_x = 0;
_z = -1;
}
void IDisposable.Dispose () { }
object IEnumerator.Current
{
get
{
return Current;
}
}
ChunkRef IEnumerator<ChunkRef>.Current
{
get
{
return Current;
}
}
public ChunkRef Current
{
get
{
if (_x >= ChunkManager.REGION_XLEN) {
throw new InvalidOperationException();
}
return _chunk;
}
}
}
} }
public class MissingChunkException : Exception public class MissingChunkException : Exception

View file

@ -1,131 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
namespace Substrate
{
public class RegionList : IEnumerable<Region>
{
private List<Region> _regions;
public RegionList (List<Region> regs)
{
_regions = regs;
}
public RegionList (RegionManager rm)
{
_regions = new List<Region>();
if (!Directory.Exists(rm.GetRegionPath())) {
throw new DirectoryNotFoundException();
}
string[] files = Directory.GetFiles(rm.GetRegionPath());
_regions.Capacity = files.Length;
foreach (string file in files) {
try {
Region r = rm.GetRegion(file);
_regions.Add(r);
}
catch (ArgumentException) {
continue;
}
}
}
IEnumerator IEnumerable.GetEnumerator () {
return (IEnumerator)GetEnumerator();
}
IEnumerator<Region> IEnumerable<Region>.GetEnumerator ()
{
return (IEnumerator<Region>)GetEnumerator();
}
public RegionEnumerator GetEnumerator ()
{
return new RegionEnumerator(_regions);
}
}
public class RegionEnumerator : IEnumerator<Region>
{
protected List<Region> _regions;
protected int _pos = -1;
public RegionEnumerator (List<Region> regs)
{
_regions = regs;
}
public RegionEnumerator (RegionManager rm)
{
_regions = new List<Region>();
if (!Directory.Exists(rm.GetRegionPath())) {
throw new DirectoryNotFoundException();
}
string[] files = Directory.GetFiles(rm.GetRegionPath());
_regions.Capacity = files.Length;
foreach (string file in files) {
try {
Region r = rm.GetRegion(file);
_regions.Add(r);
}
catch (ArgumentException) {
continue;
}
}
}
public bool MoveNext ()
{
_pos++;
return (_pos < _regions.Count);
}
public void Reset ()
{
_pos = -1;
}
void IDisposable.Dispose () { }
object IEnumerator.Current
{
get
{
return Current;
}
}
Region IEnumerator<Region>.Current
{
get
{
return Current;
}
}
public Region Current
{
get
{
try {
return _regions[_pos];
}
catch (IndexOutOfRangeException) {
throw new InvalidOperationException();
}
}
}
}
}

View file

@ -1,11 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.IO; using System.IO;
using System.Collections;
namespace Substrate namespace Substrate
{ {
public class RegionManager public class RegionManager : IEnumerable<Region>
{ {
protected string _regionPath; protected string _regionPath;
@ -72,5 +72,102 @@ namespace Substrate
return true; return true;
} }
#region IEnumerable<Region> Members
public IEnumerator<Region> GetEnumerator ()
{
return new RegionEnumerator(this);
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator ()
{
return new RegionEnumerator(this);
}
#endregion
public class RegionEnumerator : IEnumerator<Region>
{
protected List<Region> _regions;
protected int _pos = -1;
public RegionEnumerator (List<Region> regs)
{
_regions = regs;
}
public RegionEnumerator (RegionManager rm)
{
_regions = new List<Region>();
if (!Directory.Exists(rm.GetRegionPath())) {
throw new DirectoryNotFoundException();
}
string[] files = Directory.GetFiles(rm.GetRegionPath());
_regions.Capacity = files.Length;
foreach (string file in files) {
try {
Region r = rm.GetRegion(file);
_regions.Add(r);
}
catch (ArgumentException) {
continue;
}
}
}
public bool MoveNext ()
{
_pos++;
return (_pos < _regions.Count);
}
public void Reset ()
{
_pos = -1;
}
void IDisposable.Dispose () { }
object IEnumerator.Current
{
get
{
return Current;
}
}
Region IEnumerator<Region>.Current
{
get
{
return Current;
}
}
public Region Current
{
get
{
try {
return _regions[_pos];
}
catch (IndexOutOfRangeException) {
throw new InvalidOperationException();
}
}
}
}
} }
} }

View file

@ -73,7 +73,6 @@
<Compile Include="Source\BlockManager.cs" /> <Compile Include="Source\BlockManager.cs" />
<Compile Include="Source\BlockRef.cs" /> <Compile Include="Source\BlockRef.cs" />
<Compile Include="Source\Chunk.cs" /> <Compile Include="Source\Chunk.cs" />
<Compile Include="Source\ChunkEnumerator.cs" />
<Compile Include="Source\ChunkFile.cs" /> <Compile Include="Source\ChunkFile.cs" />
<Compile Include="Source\ChunkFileManager.cs" /> <Compile Include="Source\ChunkFileManager.cs" />
<Compile Include="Source\ChunkInterface.cs" /> <Compile Include="Source\ChunkInterface.cs" />
@ -118,7 +117,6 @@
<Compile Include="Source\NBT\NBTVerifier.cs" /> <Compile Include="Source\NBT\NBTVerifier.cs" />
<Compile Include="Source\Player.cs" /> <Compile Include="Source\Player.cs" />
<Compile Include="Source\Region.cs" /> <Compile Include="Source\Region.cs" />
<Compile Include="Source\RegionEnumerator.cs" />
<Compile Include="Source\RegionFile.cs" /> <Compile Include="Source\RegionFile.cs" />
<Compile Include="Source\RegionKey.cs" /> <Compile Include="Source\RegionKey.cs" />
<Compile Include="Source\RegionManager.cs" /> <Compile Include="Source\RegionManager.cs" />

View file

@ -5,8 +5,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Substrate", "Substrate.cspr
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBToolkit", "..\..\NBToolkit\NBToolkit.csproj", "{68207314-C080-4823-97F1-A6623145AA00}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBToolkit", "..\..\NBToolkit\NBToolkit.csproj", "{68207314-C080-4823-97F1-A6623145AA00}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ionic.Zlib", "..\..\Ionic.Zlib\Ionic.Zlib.csproj", "{5A137E43-7E7B-4696-8BFC-844CACAB144B}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -21,10 +19,6 @@ Global
{68207314-C080-4823-97F1-A6623145AA00}.Debug|Any CPU.Build.0 = Debug|Any CPU {68207314-C080-4823-97F1-A6623145AA00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68207314-C080-4823-97F1-A6623145AA00}.Release|Any CPU.ActiveCfg = Release|Any CPU {68207314-C080-4823-97F1-A6623145AA00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68207314-C080-4823-97F1-A6623145AA00}.Release|Any CPU.Build.0 = Release|Any CPU {68207314-C080-4823-97F1-A6623145AA00}.Release|Any CPU.Build.0 = Release|Any CPU
{5A137E43-7E7B-4696-8BFC-844CACAB144B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5A137E43-7E7B-4696-8BFC-844CACAB144B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A137E43-7E7B-4696-8BFC-844CACAB144B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A137E43-7E7B-4696-8BFC-844CACAB144B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE