diff --git a/Substrate/SubstrateCS/Examples/Examples.sln b/Substrate/SubstrateCS/Examples/Examples.sln
index b21f17f..95d0a0c 100644
--- a/Substrate/SubstrateCS/Examples/Examples.sln
+++ b/Substrate/SubstrateCS/Examples/Examples.sln
@@ -13,7 +13,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoveSpawn", "MoveSpawn\Move
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}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Relight", "Relight\Relight.csproj", "{EBDD447B-01FA-4A29-B4AB-380EC4379B5F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -45,10 +45,10 @@ Global
{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
+ {EBDD447B-01FA-4A29-B4AB-380EC4379B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EBDD447B-01FA-4A29-B4AB-380EC4379B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EBDD447B-01FA-4A29-B4AB-380EC4379B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EBDD447B-01FA-4A29-B4AB-380EC4379B5F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Substrate/SubstrateCS/Examples/Relight/Program.cs b/Substrate/SubstrateCS/Examples/Relight/Program.cs
new file mode 100644
index 0000000..7c8e540
--- /dev/null
+++ b/Substrate/SubstrateCS/Examples/Relight/Program.cs
@@ -0,0 +1,49 @@
+using System;
+using Substrate;
+
+namespace Relight
+{
+ class Program
+ {
+ static void Main (string[] args)
+ {
+ if (args.Length < 1) {
+ Console.WriteLine("You must specify a target directory");
+ return;
+ }
+ string dest = args[0];
+
+ // Load the world, supporting either alpha or beta format
+ INBTWorld world;
+ if (args.Length >= 2 && args[1] == "alpha") {
+ world = AlphaWorld.Open(dest);
+ }
+ else {
+ world = BetaWorld.Open(dest);
+ }
+
+ // Grab a generic chunk manager reference
+ IChunkManager cm = world.GetChunkManager();
+
+ // First blank out all of the lighting in all of the chunks
+ foreach (ChunkRef chunk in cm) {
+ chunk.ResetBlockLight();
+ chunk.ResetSkyLight();
+ cm.Save();
+
+ Console.WriteLine("Reset Chunk {0},{1}", chunk.X, chunk.Z);
+ }
+
+ // In a separate pass, reconstruct the light
+ foreach (ChunkRef chunk in cm) {
+ chunk.RebuildBlockLight();
+ chunk.RebuildSkyLight();
+
+ // Save the chunk to disk so it doesn't hang around in RAM
+ cm.Save();
+
+ Console.WriteLine("Lit Chunk {0},{1}", chunk.X, chunk.Z);
+ }
+ }
+ }
+}
diff --git a/Substrate/SubstrateCS/Examples/Relight/Properties/AssemblyInfo.cs b/Substrate/SubstrateCS/Examples/Relight/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..474634a
--- /dev/null
+++ b/Substrate/SubstrateCS/Examples/Relight/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("Relight")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Relight")]
+[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("b21635dd-f744-4740-842a-f86781787961")]
+
+// 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/Relight/Relight.csproj b/Substrate/SubstrateCS/Examples/Relight/Relight.csproj
new file mode 100644
index 0000000..1919f5b
--- /dev/null
+++ b/Substrate/SubstrateCS/Examples/Relight/Relight.csproj
@@ -0,0 +1,52 @@
+
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {EBDD447B-01FA-4A29-B4AB-380EC4379B5F}
+ Exe
+ Properties
+ Relight
+ Relight
+ 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/Source/ChunkCache.cs b/Substrate/SubstrateCS/Source/ChunkCache.cs
new file mode 100644
index 0000000..39c15b9
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/ChunkCache.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Collections;
+
+namespace Substrate
+{
+ public class ChunkCache : IChunkCache
+ {
+ private Dictionary _cache;
+ private Dictionary _dirty;
+
+ public ChunkCache ()
+ {
+ _cache = new Dictionary();
+ _dirty = new Dictionary();
+ }
+
+ #region IChunkCache Members
+
+ public bool Insert (ChunkRef chunk)
+ {
+ ChunkKey key = new ChunkKey(chunk.X, chunk.Z);
+
+ WeakReference wref;
+ if (!_cache.TryGetValue(key, out wref)) {
+ _cache[key] = new WeakReference(chunk);
+ return true;
+ }
+
+ if (!wref.IsAlive) {
+ wref.Target = chunk;
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool Remove (ChunkKey key)
+ {
+ _dirty.Remove(key);
+ return _cache.Remove(key);
+ }
+
+ public ChunkRef Fetch (ChunkKey key)
+ {
+ WeakReference wref;
+ if (!_cache.TryGetValue(key, out wref)) {
+ return null;
+ }
+
+ return wref.Target as ChunkRef;
+ }
+
+ public IEnumerator GetDirtyEnumerator ()
+ {
+ return _dirty.Values.GetEnumerator();
+ }
+
+ public void ClearDirty ()
+ {
+ _dirty.Clear();
+ }
+
+ public bool MarkChunkDirty (ChunkRef chunk)
+ {
+ int cx = chunk.X;
+ int cz = chunk.Z;
+
+ ChunkKey k = new ChunkKey(cx, cz);
+ if (!_dirty.ContainsKey(k)) {
+ _dirty.Add(k, chunk);
+ return true;
+ }
+ return false;
+ }
+
+ public bool MarkChunkClean (ChunkRef chunk)
+ {
+ int cx = chunk.X;
+ int cz = chunk.Z;
+
+ ChunkKey k = new ChunkKey(cx, cz);
+ if (_dirty.ContainsKey(k)) {
+ _dirty.Remove(k);
+ return true;
+ }
+ return false;
+ }
+
+ #endregion
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/ChunkManager.cs b/Substrate/SubstrateCS/Source/ChunkManager.cs
index eedf08c..254730d 100644
--- a/Substrate/SubstrateCS/Source/ChunkManager.cs
+++ b/Substrate/SubstrateCS/Source/ChunkManager.cs
@@ -5,7 +5,7 @@ using System.Collections;
namespace Substrate
{
- public class ChunkManager : IChunkManager, IChunkCache, IEnumerable
+ public class ChunkManager : IChunkManager, IEnumerable
{
public const int REGION_XLEN = 32;
public const int REGION_ZLEN = 32;
@@ -18,21 +18,25 @@ namespace Substrate
protected RegionManager _regionMan;
- protected Dictionary _cache;
- protected Dictionary _dirty;
+ //protected Dictionary _cache;
+ //protected Dictionary _dirty;
- public ChunkManager (RegionManager rm)
+ protected ChunkCache _cache;
+
+ public ChunkManager (RegionManager rm, ChunkCache cache)
{
_regionMan = rm;
- _cache = new Dictionary();
- _dirty = new Dictionary();
+ _cache = cache;
+ //_cache = new Dictionary();
+ //_dirty = new Dictionary();
}
public ChunkManager (ChunkManager cm)
{
_regionMan = cm._regionMan;
- _cache = new Dictionary();
- _dirty = new Dictionary();
+ _cache = cm._cache;
+ //_cache = new Dictionary();
+ //_dirty = new Dictionary();
}
public int ChunkGlobalX (int cx)
@@ -72,7 +76,7 @@ namespace Substrate
return null;
}
- return r.GetChunkRef(cx & REGION_XMASK, cz & REGION_ZMASK, this);
+ return r.GetChunkRef(cx & REGION_XMASK, cz & REGION_ZMASK);
}
public bool ChunkExists (int cx, int cz)
@@ -94,10 +98,10 @@ namespace Substrate
r = _regionMan.CreateRegion(rx, rz);
}
- return r.CreateChunk(cx & REGION_XMASK, cz & REGION_ZMASK, this);
+ return r.CreateChunk(cx & REGION_XMASK, cz & REGION_ZMASK);
}
- public bool MarkChunkDirty (ChunkRef chunk)
+ /*public bool MarkChunkDirty (ChunkRef chunk)
{
Region r = GetRegion(chunk.X, chunk.Z);
if (r == null) {
@@ -125,16 +129,25 @@ namespace Substrate
r.MarkChunkClean(chunk);
return true;
- }
+ }*/
public int Save ()
{
int saved = 0;
- foreach (Region r in _dirty.Values) {
- saved += r.Save();
+ IEnumerator en = _cache.GetDirtyEnumerator();
+ while (en.MoveNext()) {
+ ChunkRef chunk = en.Current;
+
+ Region r = GetRegion(chunk.X, chunk.Z);
+ if (r == null) {
+ continue;
+ }
+
+ chunk.Save(r.GetChunkOutStream(chunk.LocalX, chunk.LocalZ));
+ saved++;
}
- _dirty.Clear();
+ _cache.ClearDirty();
return saved;
}
@@ -160,10 +173,6 @@ namespace Substrate
}
if (r.ChunkCount() == 0) {
- RegionKey k = new RegionKey(r.X, r.Z);
- _cache.Remove(k);
- _dirty.Remove(k);
-
_regionMan.DeleteRegion(r.X, r.Z);
}
@@ -245,7 +254,7 @@ namespace Substrate
_region = _enum.Current;
}
if (MoveNextInRegion()) {
- _chunk = _region.GetChunkRef(_x, _z, _cm);
+ _chunk = _region.GetChunkRef(_x, _z);
return true;
}
}
diff --git a/Substrate/SubstrateCS/Source/Region.cs b/Substrate/SubstrateCS/Source/Region.cs
index 152cb49..6b83ed2 100644
--- a/Substrate/SubstrateCS/Source/Region.cs
+++ b/Substrate/SubstrateCS/Source/Region.cs
@@ -8,7 +8,7 @@ namespace Substrate
{
using NBT;
- public class Region : IDisposable, IChunkContainer, IChunkCache
+ public class Region : IDisposable, IChunkContainer
{
private const int XDIM = 32;
private const int ZDIM = 32;
@@ -27,8 +27,10 @@ namespace Substrate
protected WeakReference _regionFile;
- protected Dictionary _cache;
- protected Dictionary _dirty;
+ //protected Dictionary _cache;
+ //protected Dictionary _dirty;
+
+ protected ChunkCache _cache;
public int X
{
@@ -50,24 +52,26 @@ namespace Substrate
get { return ZDIM; }
}
- public Region (RegionManager rm, int rx, int rz)
+ public Region (RegionManager rm, ChunkCache cache, int rx, int rz)
{
_regionMan = rm;
+ _cache = cache;
_regionFile = new WeakReference(null);
_rx = rx;
_rz = rz;
- _cache = new Dictionary();
- _dirty = new Dictionary();
+ //_cache = new Dictionary();
+ //_dirty = new Dictionary();
if (!File.Exists(GetFilePath())) {
throw new FileNotFoundException();
}
}
- public Region (RegionManager rm, string filename)
+ public Region (RegionManager rm, ChunkCache cache, string filename)
{
_regionMan = rm;
+ _cache = cache;
_regionFile = new WeakReference(null);
ParseFileName(filename, out _rx, out _rz);
@@ -217,32 +221,25 @@ namespace Substrate
return count;
}
- public ChunkRef GetChunkRef (int lcx, int lcz, IChunkCache cache)
+ public ChunkRef GetChunkRef (int lcx, int lcz)
{
if (!LocalBoundsCheck(lcx, lcz)) {
Region alt = GetForeignRegion(lcx, lcz);
- return (alt == null) ? null : alt.GetChunkRef(ForeignX(lcx), ForeignZ(lcz), cache);
+ return (alt == null) ? null : alt.GetChunkRef(ForeignX(lcx), ForeignZ(lcz));
}
- ChunkKey k = new ChunkKey(lcx, lcz);
-
- ChunkRef c = null;
-
- WeakReference chunkref = null;
- if (_cache.TryGetValue(k, out chunkref)) {
- c = chunkref.Target as ChunkRef;
- }
- else {
- _cache.Add(k, new WeakReference(null));
- }
+ int cx = lcx + _rx * ChunkManager.REGION_XLEN;
+ int cz = lcz + _rz * ChunkManager.REGION_ZLEN;
+ ChunkKey k = new ChunkKey(cx, cz);
+ ChunkRef c = _cache.Fetch(k);
if (c != null) {
return c;
}
try {
- c = new ChunkRef(this, cache, lcx, lcz);
- _cache[k].Target = c;
+ c = new ChunkRef(this, _cache, lcx, lcz);
+ _cache.Insert(c);
return c;
}
catch (MissingChunkException) {
@@ -251,15 +248,10 @@ namespace Substrate
}
public ChunkRef CreateChunk (int lcx, int lcz)
- {
- return CreateChunk(lcx, lcz, this);
- }
-
- public ChunkRef CreateChunk (int lcx, int lcz, IChunkCache cache)
{
if (!LocalBoundsCheck(lcx, lcz)) {
Region alt = GetForeignRegion(lcx, lcz);
- return (alt == null) ? null : alt.CreateChunk(ForeignX(lcx), ForeignZ(lcz), cache);
+ return (alt == null) ? null : alt.CreateChunk(ForeignX(lcx), ForeignZ(lcz));
}
DeleteChunk(lcx, lcz);
@@ -270,9 +262,8 @@ namespace Substrate
Chunk c = new Chunk(cx, cz);
c.Save(GetChunkOutStream(lcx, lcz));
- ChunkRef cr = new ChunkRef(this, cache, lcx, lcz);
- ChunkKey k = new ChunkKey(lcx, lcz);
- _cache[k] = new WeakReference(cr);
+ ChunkRef cr = new ChunkRef(this, _cache, lcx, lcz);
+ _cache.Insert(cr);
return cr;
}
@@ -314,11 +305,6 @@ namespace Substrate
return new Chunk(GetChunkTree(lcx, lcz));
}
- public ChunkRef GetChunkRef (int lcx, int lcz)
- {
- return GetChunkRef(lcx, lcz, this);
- }
-
public bool ChunkExists (int lcx, int lcz)
{
if (!LocalBoundsCheck(lcx, lcz)) {
@@ -346,7 +332,6 @@ namespace Substrate
ChunkKey k = new ChunkKey(lcx, lcz);
_cache.Remove(k);
- _dirty.Remove(k);
if (ChunkCount() == 0) {
_regionMan.DeleteRegion(X, Z);
@@ -358,22 +343,20 @@ namespace Substrate
public int Save ()
{
int saved = 0;
- foreach (ChunkRef c in _dirty.Values) {
- int cx = c.X;
- int cz = c.Z;
- int lcx = cx - _rx * ChunkManager.REGION_XLEN;
- int lcz = cz - _rz * ChunkManager.REGION_ZLEN;
+ IEnumerator en = _cache.GetDirtyEnumerator();
+ while (en.MoveNext()) {
+ ChunkRef chunk = en.Current;
- if (!ChunkExists(lcx, lcz)) {
+ if (!ChunkExists(chunk.LocalX, chunk.LocalZ)) {
throw new MissingChunkException();
}
- if (c.Save(GetChunkOutStream(lcx, lcz))) {
+ if (chunk.Save(GetChunkOutStream(chunk.LocalX, chunk.LocalZ))) {
saved++;
}
}
- _dirty.Clear();
+ _cache.ClearDirty();
return saved;
}
@@ -387,7 +370,7 @@ namespace Substrate
#region IChunkCache Members
- public bool MarkChunkDirty (ChunkRef chunk)
+ /*public bool MarkChunkDirty (ChunkRef chunk)
{
int cx = chunk.X;
int cz = chunk.Z;
@@ -415,7 +398,7 @@ namespace Substrate
return true;
}
return false;
- }
+ }*/
#endregion
diff --git a/Substrate/SubstrateCS/Source/RegionManager.cs b/Substrate/SubstrateCS/Source/RegionManager.cs
index 0f3dc7c..7572a59 100644
--- a/Substrate/SubstrateCS/Source/RegionManager.cs
+++ b/Substrate/SubstrateCS/Source/RegionManager.cs
@@ -25,9 +25,12 @@ namespace Substrate
protected Dictionary _cache;
- public RegionManager (string regionDir)
+ protected ChunkCache _chunkCache;
+
+ public RegionManager (string regionDir, ChunkCache cache)
{
_regionPath = regionDir;
+ _chunkCache = cache;
_cache = new Dictionary();
}
@@ -38,7 +41,7 @@ namespace Substrate
try {
if (_cache.TryGetValue(k, out r) == false) {
- r = new Region(this, rx, rz);
+ r = new Region(this, _chunkCache, rx, rz);
_cache.Add(k, r);
}
return r;
@@ -64,7 +67,7 @@ namespace Substrate
}
- r = new Region(this, rx, rz);
+ r = new Region(this, _chunkCache, rx, rz);
RegionKey k = new RegionKey(rx, rz);
_cache[k] = r;
@@ -113,7 +116,7 @@ namespace Substrate
return true;
}
- public int Save ()
+ /*public int Save ()
{
int saved = 0;
foreach (Region r in _cache.Values) {
@@ -121,7 +124,7 @@ namespace Substrate
}
return saved;
- }
+ }*/
#region IEnumerable Members
diff --git a/Substrate/SubstrateCS/Source/World.cs b/Substrate/SubstrateCS/Source/World.cs
index 7dbe9ba..f6e98df 100644
--- a/Substrate/SubstrateCS/Source/World.cs
+++ b/Substrate/SubstrateCS/Source/World.cs
@@ -281,8 +281,8 @@ namespace Substrate
{
_level.Save();
- foreach (KeyValuePair rm in _regionMgrs) {
- rm.Value.Save();
+ foreach (KeyValuePair cm in _chunkMgrs) {
+ cm.Value.Save();
}
}
@@ -301,8 +301,10 @@ namespace Substrate
Directory.CreateDirectory(path);
}
- RegionManager rm = new RegionManager(path);
- ChunkManager cm = new ChunkManager(rm);
+ ChunkCache cc = new ChunkCache();
+
+ RegionManager rm = new RegionManager(path, cc);
+ ChunkManager cm = new ChunkManager(rm, cc);
BlockManager bm = new BlockManager(cm);
_regionMgrs[dim] = rm;
diff --git a/Substrate/SubstrateCS/Substrate.csproj b/Substrate/SubstrateCS/Substrate.csproj
index 0724676..e71527a 100644
--- a/Substrate/SubstrateCS/Substrate.csproj
+++ b/Substrate/SubstrateCS/Substrate.csproj
@@ -59,8 +59,11 @@
Assemblies\Ionic.Zlib.dll
+
+
+