forked from mirrors/NBTExplorer
Major restructuring in block/chunk/region handling. Abstracted block and chunk interfaces.
This commit is contained in:
parent
d094a3cb47
commit
951e912a57
18 changed files with 1084 additions and 50 deletions
86
NBToolkit/NBToolkit/BlockManager.cs
Normal file
86
NBToolkit/NBToolkit/BlockManager.cs
Normal file
|
@ -0,0 +1,86 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class BlockManager
|
||||
{
|
||||
public const int MIN_X = -32000000;
|
||||
public const int MAX_X = 32000000;
|
||||
public const int MIN_Y = 0;
|
||||
public const int MAX_Y = 128;
|
||||
public const int MIN_Z = -32000000;
|
||||
public const int MAX_Z = 32000000;
|
||||
|
||||
public const int CHUNK_XLEN = 16;
|
||||
public const int CHUNK_YLEN = 128;
|
||||
public const int CHUNK_ZLEN = 16;
|
||||
|
||||
public const int CHUNK_XLOG = 4;
|
||||
public const int CHUNK_YLOG = 7;
|
||||
public const int CHUNK_ZLOG = 4;
|
||||
|
||||
public const int CHUNK_XMASK = 0xF;
|
||||
public const int CHUNK_YMASK = 0x7F;
|
||||
public const int CHUNK_ZMASK = 0xF;
|
||||
|
||||
protected ChunkManager _chunkMan;
|
||||
|
||||
public BlockManager (ChunkManager cm)
|
||||
{
|
||||
_chunkMan = cm;
|
||||
}
|
||||
|
||||
public int GetBlockID (int x, int y, int z)
|
||||
{
|
||||
if (x < MIN_X || x >= MAX_X)
|
||||
return 0;
|
||||
if (y < MIN_Y || y >= MAX_Y)
|
||||
return 0;
|
||||
if (z < MIN_Z || z >= MAX_Z)
|
||||
return 0;
|
||||
|
||||
Chunk c = GetChunk(x, y, z);
|
||||
if (c == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return c.GetBlockID(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
|
||||
}
|
||||
|
||||
int GetBlockData (int x, int y, int z) { return 0; }
|
||||
|
||||
int GetBlockLight (int x, int y, int z) { return 0; }
|
||||
|
||||
int GetBlockSkylight (int x, int y, int z) { return 0; }
|
||||
|
||||
void SetBlock (int x, int y, int z, int id, int data) { }
|
||||
|
||||
public bool SetBlockID (int x, int y, int z, int id)
|
||||
{
|
||||
if (x < MIN_X || x >= MAX_X)
|
||||
return false;
|
||||
if (y < MIN_Y || y >= MAX_Y)
|
||||
return false;
|
||||
if (z < MIN_Z || z >= MAX_Z)
|
||||
return false;
|
||||
|
||||
Chunk c = GetChunk(x, y, z);
|
||||
if (c == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return c.SetBlockID(x & CHUNK_XMASK, y, z & CHUNK_ZMASK, id);
|
||||
}
|
||||
|
||||
void SetBlockData (int x, int y, int z, int data) { }
|
||||
|
||||
public Chunk GetChunk (int x, int y, int z)
|
||||
{
|
||||
x >>= CHUNK_XLOG;
|
||||
z >>= CHUNK_ZLOG;
|
||||
return _chunkMan.GetChunk(x, z);
|
||||
}
|
||||
}
|
||||
}
|
105
NBToolkit/NBToolkit/Chunk.cs
Normal file
105
NBToolkit/NBToolkit/Chunk.cs
Normal file
|
@ -0,0 +1,105 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NBT;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class Chunk
|
||||
{
|
||||
protected int _cx;
|
||||
protected int _cz;
|
||||
|
||||
protected NBT_Tree _nbt = null;
|
||||
protected NBT_ByteArray _blocks = null;
|
||||
|
||||
protected bool _dirty = false;
|
||||
|
||||
protected ChunkManager _chunkMan;
|
||||
|
||||
public Chunk (ChunkManager cm, int cx, int cz)
|
||||
{
|
||||
_chunkMan = cm;
|
||||
_cx = cx;
|
||||
_cz = cz;
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return _cx;
|
||||
}
|
||||
}
|
||||
|
||||
public int Z
|
||||
{
|
||||
get
|
||||
{
|
||||
return _cz;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Save ()
|
||||
{
|
||||
if (_dirty) {
|
||||
if (SaveTree()) {
|
||||
_dirty = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected NBT_Tree GetTree ()
|
||||
{
|
||||
if (_nbt != null) {
|
||||
return _nbt;
|
||||
}
|
||||
|
||||
Region r = _chunkMan.GetRegion(_cx, _cz);
|
||||
_nbt = r.GetChunkTree(_cx & ChunkManager.REGION_XMASK, _cz & ChunkManager.REGION_ZMASK);
|
||||
|
||||
return _nbt;
|
||||
}
|
||||
|
||||
protected bool SaveTree ()
|
||||
{
|
||||
if (_nbt != null) {
|
||||
_blocks = null;
|
||||
|
||||
Region r = _chunkMan.GetRegion(_cx, _cz);
|
||||
return r.SaveChunkTree(_cx & ChunkManager.REGION_XMASK, _cz & ChunkManager.REGION_ZMASK, _nbt);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetBlockID (int x, int y, int z)
|
||||
{
|
||||
if (_blocks == null) {
|
||||
_blocks = GetTree().getRoot().findTagByName("Level").findTagByName("Blocks").value.toByteArray();
|
||||
}
|
||||
|
||||
return _blocks.data[x << 11 | z << 7 | y];
|
||||
}
|
||||
|
||||
public bool SetBlockID (int x, int y, int z, int id)
|
||||
{
|
||||
if (_blocks == null) {
|
||||
_blocks = GetTree().getRoot().findTagByName("Level").findTagByName("Blocks").value.toByteArray();
|
||||
}
|
||||
|
||||
int index = x << 11 | z << 7 | y;
|
||||
if (_blocks.data[index] == id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_blocks.data[index] = (byte)id;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
145
NBToolkit/NBToolkit/ChunkEnumerator.cs
Normal file
145
NBToolkit/NBToolkit/ChunkEnumerator.cs
Normal file
|
@ -0,0 +1,145 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class ChunkList : IEnumerable<Chunk>
|
||||
{
|
||||
//private List<Region> _regions;
|
||||
|
||||
private ChunkManager _cm = null;
|
||||
private 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<Chunk> IEnumerable<Chunk>.GetEnumerator ()
|
||||
{
|
||||
return (IEnumerator<Chunk>)GetEnumerator();
|
||||
}
|
||||
|
||||
public ChunkEnumerator GetEnumerator ()
|
||||
{
|
||||
return new ChunkEnumerator(_cm, _region);
|
||||
}
|
||||
}
|
||||
|
||||
public class ChunkEnumerator : IEnumerator<Chunk>
|
||||
{
|
||||
protected Region _region;
|
||||
protected ChunkManager _cm;
|
||||
|
||||
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 bool MoveNext ()
|
||||
{
|
||||
if (_enum == null) {
|
||||
return MoveNextInRegion();
|
||||
}
|
||||
else {
|
||||
while (true) {
|
||||
if (_x >= ChunkManager.REGION_XLEN) {
|
||||
if (!_enum.MoveNext()) {
|
||||
return false;
|
||||
}
|
||||
_x = 0;
|
||||
_z = -1;
|
||||
}
|
||||
if (MoveNextInRegion()) {
|
||||
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 = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Chunk IEnumerator<Chunk>.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public Chunk Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_x >= ChunkManager.REGION_XLEN) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return _cm.GetChunkInRegion(_region, _x, _z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
NBToolkit/NBToolkit/ChunkKey.cs
Normal file
28
NBToolkit/NBToolkit/ChunkKey.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class ChunkKey : IEquatable<ChunkKey>
|
||||
{
|
||||
protected int cx;
|
||||
protected int cz;
|
||||
|
||||
public ChunkKey (int _cx, int _cz)
|
||||
{
|
||||
cx = _cx;
|
||||
cz = _cz;
|
||||
}
|
||||
|
||||
public bool Equals (ChunkKey ck)
|
||||
{
|
||||
return this.cx == ck.cx && this.cz == ck.cz;
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return cx ^ cz;
|
||||
}
|
||||
}
|
||||
}
|
69
NBToolkit/NBToolkit/ChunkManager.cs
Normal file
69
NBToolkit/NBToolkit/ChunkManager.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class ChunkManager
|
||||
{
|
||||
public const int REGION_XLEN = 32;
|
||||
public const int REGION_ZLEN = 32;
|
||||
|
||||
public const int REGION_XLOG = 5;
|
||||
public const int REGION_ZLOG = 5;
|
||||
|
||||
public const int REGION_XMASK = 0x1F;
|
||||
public const int REGION_ZMASK = 0x1F;
|
||||
|
||||
protected RegionManager _regionMan;
|
||||
|
||||
protected Dictionary<ChunkKey, WeakReference> _cache;
|
||||
|
||||
public ChunkManager (RegionManager rm)
|
||||
{
|
||||
_regionMan = rm;
|
||||
_cache = new Dictionary<ChunkKey, WeakReference>();
|
||||
}
|
||||
|
||||
public Chunk GetChunk (int cx, int cz)
|
||||
{
|
||||
ChunkKey k = new ChunkKey(cx, cz);
|
||||
|
||||
Chunk c = null;
|
||||
if (_cache.ContainsKey(k)) {
|
||||
c = _cache[k].Target as Chunk;
|
||||
}
|
||||
else {
|
||||
_cache.Add(k, new WeakReference(null));
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
return c;
|
||||
}
|
||||
|
||||
c = new Chunk(this, cx, cz);
|
||||
_cache[k].Target = c;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public Chunk GetChunkInRegion (Region r, int lcx, int lcz)
|
||||
{
|
||||
int cx = r.X * REGION_XLEN + lcx;
|
||||
int cz = r.Z * REGION_ZLEN + lcz;
|
||||
return GetChunk(cx, cz);
|
||||
}
|
||||
|
||||
public Region GetRegion (int cx, int cz)
|
||||
{
|
||||
cx >>= REGION_XLOG;
|
||||
cz >>= REGION_ZLOG;
|
||||
return _regionMan.GetRegion(cx, cz);
|
||||
}
|
||||
|
||||
public RegionManager GetRegionManager ()
|
||||
{
|
||||
return _regionMan;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,22 @@ namespace NBToolkit
|
|||
class Harness
|
||||
{
|
||||
public void Run (TKOptions opt, TKFilter filter) {
|
||||
string[] regions = RegionFileCache.GetRegionFileList(opt.OPT_WORLD);
|
||||
World world = new World(opt.OPT_WORLD);
|
||||
RegionList regions = new RegionList(world.GetRegionManager());
|
||||
|
||||
foreach (Region region in regions) {
|
||||
Console.WriteLine(region.GetFileName());
|
||||
|
||||
for (int x = 0; x < ChunkManager.REGION_XLEN; x++) {
|
||||
for (int z = 0; z < ChunkManager.REGION_ZLEN; z++) {
|
||||
if (!region.ChunkExists(x, z)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*string[] regions = RegionFileCache.GetRegionFileList(opt.OPT_WORLD);
|
||||
|
||||
foreach (string p in regions) {
|
||||
Console.WriteLine(p);
|
||||
|
@ -85,7 +100,7 @@ namespace NBToolkit
|
|||
zipStream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
protected bool BlockScan (NBT_Tag level, int val)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>NBToolkit</RootNamespace>
|
||||
<AssemblyName>NBToolkit</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
|
@ -53,10 +53,17 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BlockManager.cs" />
|
||||
<Compile Include="Chunk.cs" />
|
||||
<Compile Include="ChunkManager.cs" />
|
||||
<Compile Include="Harness.cs" />
|
||||
<Compile Include="NBT.cs" />
|
||||
<Compile Include="NDesk\Options.cs" />
|
||||
<Compile Include="Oregen.cs" />
|
||||
<Compile Include="Region.cs" />
|
||||
<Compile Include="RegionEnumerator.cs" />
|
||||
<Compile Include="RegionKey.cs" />
|
||||
<Compile Include="RegionManager.cs" />
|
||||
<Compile Include="Replace.cs" />
|
||||
<Compile Include="TKFilter.cs" />
|
||||
<Compile Include="TKOptions.cs" />
|
||||
|
@ -64,6 +71,7 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RegionFile.cs" />
|
||||
<Compile Include="RegionFileCache.cs" />
|
||||
<Compile Include="World.cs" />
|
||||
<Compile Include="Zlib\Crc32.cs" />
|
||||
<Compile Include="Zlib\Deflate.cs" />
|
||||
<Compile Include="Zlib\DeflateStream.cs" />
|
||||
|
|
Binary file not shown.
|
@ -59,7 +59,7 @@ namespace NBToolkit
|
|||
{ "max=", "Generates deposits no higher than depth {VAL} (0-127)",
|
||||
v => OPT_MAX = Convert.ToInt32(v) % 128 },
|
||||
{ "s|size=", "Generates deposits containing roughly up to {VAL} blocks",
|
||||
v => OPT_MIN = Convert.ToInt32(v) % 128 },
|
||||
v => OPT_SIZE = Convert.ToInt32(v) % 128 },
|
||||
{ "oo=", "Generated deposits can replace other existing ores",
|
||||
v => OPT_OO = true },
|
||||
{ "oa=", "Generated deposits can replace any existing block (incl. air)",
|
||||
|
@ -140,6 +140,95 @@ namespace NBToolkit
|
|||
}
|
||||
}
|
||||
|
||||
public class MathHelper
|
||||
{
|
||||
private static float[] trigTable = new float[65536];
|
||||
|
||||
static MathHelper ()
|
||||
{
|
||||
for (int i = 0; i < 65536; i++) {
|
||||
trigTable[i] = (float)Math.Sin(i * Math.PI * 2.0D / 65536.0D);
|
||||
}
|
||||
}
|
||||
|
||||
public static float Sin(float angle)
|
||||
{
|
||||
return trigTable[((int)(angle * 10430.378F) & 0xFFFF)];
|
||||
}
|
||||
|
||||
public static float Cos(float angle) {
|
||||
return trigTable[((int)(angle * 10430.378F + 16384.0F) & 0xFFFF)];
|
||||
}
|
||||
}
|
||||
|
||||
public class NativeOreGen {
|
||||
private int _blockId;
|
||||
private int _size;
|
||||
|
||||
private static Random rand = new Random();
|
||||
|
||||
public NativeOreGen(int blockId, int size)
|
||||
{
|
||||
_blockId = blockId;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
public bool GenerateDeposit (NBT_ByteArray blocks, NBT_ByteArray data, int x, int y, int z)
|
||||
{
|
||||
float rpi = (float)(rand.NextDouble() * Math.PI);
|
||||
|
||||
double x1 = x + 8 + MathHelper.Sin(rpi) * _size / 8.0F;
|
||||
double x2 = x + 8 - MathHelper.Sin(rpi) * _size / 8.0F;
|
||||
double z1 = z + 8 + MathHelper.Cos(rpi) * _size / 8.0F;
|
||||
double z2 = z + 8 - MathHelper.Cos(rpi) * _size / 8.0F;
|
||||
|
||||
double y1 = y + rand.Next(3) + 2;
|
||||
double y2 = y + rand.Next(3) + 2;
|
||||
|
||||
for (int i = 0; i <= _size; i++) {
|
||||
double xPos = x1 + (x2 - x1) * i / _size;
|
||||
double yPos = y1 + (y2 - y1) * i / _size;
|
||||
double zPos = z1 + (z2 - z1) * i / _size;
|
||||
|
||||
double fuzz = rand.NextDouble() * _size / 16.0D;
|
||||
double fuzzXZ = (MathHelper.Sin((float)(i * Math.PI / _size)) + 1.0F) * fuzz + 1.0D;
|
||||
double fuzzY = (MathHelper.Sin((float)(i * Math.PI / _size)) + 1.0F) * fuzz + 1.0D;
|
||||
|
||||
int xStart = (int)(xPos - fuzzXZ / 2.0D);
|
||||
int yStart = (int)(yPos - fuzzY / 2.0D);
|
||||
int zStart = (int)(zPos - fuzzXZ / 2.0D);
|
||||
|
||||
int xEnd = (int)(xPos + fuzzXZ / 2.0D);
|
||||
int yEnd = (int)(yPos + fuzzY / 2.0D);
|
||||
int zEnd = (int)(zPos + fuzzXZ / 2.0D);
|
||||
|
||||
for (int ix = xStart; ix <= xEnd; ix++) {
|
||||
double xThresh = (ix + 0.5D - xPos) / (fuzzXZ / 2.0D);
|
||||
if (xThresh * xThresh < 1.0D) {
|
||||
for (int iy = yStart; iy <= yEnd; iy++) {
|
||||
double yThresh = (iy + 0.5D - yPos) / (fuzzY / 2.0D);
|
||||
if (xThresh * xThresh + yThresh * yThresh < 1.0D) {
|
||||
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) {
|
||||
//Apply
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int BlockIndex (int x, int y, int z)
|
||||
{
|
||||
return y + (z * 128 + x * 128 * 16);
|
||||
}
|
||||
}
|
||||
|
||||
public class Oregen : TKFilter
|
||||
{
|
||||
public const int BLOCK_STONE = 1;
|
||||
|
|
|
@ -8,9 +8,9 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTitle("NBToolkit")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("NBToolkit")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
|
||||
[assembly: AssemblyCopyright("Copyright © Justin Aquadro 2011")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
|
155
NBToolkit/NBToolkit/Region.cs
Normal file
155
NBToolkit/NBToolkit/Region.cs
Normal file
|
@ -0,0 +1,155 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
using NBT;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class Region
|
||||
{
|
||||
protected int _rx;
|
||||
protected int _rz;
|
||||
|
||||
protected RegionManager _regionMan;
|
||||
|
||||
protected static Regex _namePattern = new Regex("r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mcr$");
|
||||
|
||||
protected WeakReference _regionFile;
|
||||
|
||||
public Region (RegionManager rm, int rx, int rz)
|
||||
{
|
||||
_regionMan = rm;
|
||||
_regionFile = new WeakReference(null);
|
||||
_rx = rx;
|
||||
_rz = rz;
|
||||
|
||||
if (!File.Exists(GetFilePath())) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
public Region (RegionManager rm, string filename)
|
||||
{
|
||||
_regionMan = rm;
|
||||
_regionFile = new WeakReference(null);
|
||||
|
||||
ParseFileName(filename, out _rx, out _rz);
|
||||
|
||||
if (!File.Exists(Path.Combine(_regionMan.GetRegionPath(), filename))) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return _rx;
|
||||
}
|
||||
}
|
||||
|
||||
public int Z
|
||||
{
|
||||
get
|
||||
{
|
||||
return _rz;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFileName ()
|
||||
{
|
||||
return "r." + _rx + "." + _rz + ".mcr";
|
||||
|
||||
}
|
||||
|
||||
public static bool TestFileName (string filename)
|
||||
{
|
||||
Match match = _namePattern.Match(filename);
|
||||
if (!match.Success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ParseFileName (string filename, out int x, out int z)
|
||||
{
|
||||
x = 0;
|
||||
z = 0;
|
||||
|
||||
Match match = _namePattern.Match(filename);
|
||||
if (!match.Success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
x = Convert.ToInt32(match.Groups[1].Value);
|
||||
z = Convert.ToInt32(match.Groups[2].Value);
|
||||
return true;
|
||||
}
|
||||
|
||||
public string GetFilePath ()
|
||||
{
|
||||
return System.IO.Path.Combine(_regionMan.GetRegionPath(), GetFileName());
|
||||
}
|
||||
|
||||
protected RegionFile GetRegionFile ()
|
||||
{
|
||||
RegionFile rf = _regionFile.Target as RegionFile;
|
||||
if (rf == null) {
|
||||
rf = new RegionFile(GetFilePath());
|
||||
_regionFile.Target = rf;
|
||||
}
|
||||
|
||||
return rf;
|
||||
}
|
||||
|
||||
public NBT_Tree GetChunkTree (int lcx, int lcz)
|
||||
{
|
||||
RegionFile rf = GetRegionFile();
|
||||
Stream nbtstr = rf.GetChunkDataInputStream(lcx, lcz);
|
||||
if (nbtstr == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NBT_Tree(nbtstr);
|
||||
}
|
||||
|
||||
public bool SaveChunkTree (int lcx, int lcz, NBT_Tree tree)
|
||||
{
|
||||
RegionFile rf = GetRegionFile();
|
||||
Stream zipstr = rf.GetChunkDataOutputStream(lcx, lcz);
|
||||
if (zipstr == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tree.WriteTo(zipstr);
|
||||
zipstr.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ChunkExists (int lcx, int lcz)
|
||||
{
|
||||
RegionFile rf = GetRegionFile();
|
||||
return rf.HasChunk(lcx, lcz);
|
||||
}
|
||||
|
||||
public int ChunkCount ()
|
||||
{
|
||||
RegionFile rf = GetRegionFile();
|
||||
|
||||
int count = 0;
|
||||
for (int x = 0; x < ChunkManager.REGION_XLEN; x++) {
|
||||
for (int z = 0; z < ChunkManager.REGION_ZLEN; z++) {
|
||||
if (rf.HasChunk(x, z)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
131
NBToolkit/NBToolkit/RegionEnumerator.cs
Normal file
131
NBToolkit/NBToolkit/RegionEnumerator.cs
Normal file
|
@ -0,0 +1,131 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,18 +5,25 @@ using System.IO;
|
|||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class RegionFileCache
|
||||
/*public class RegionFileCache
|
||||
{
|
||||
private const int MAX_CACHE_SIZE = 256;
|
||||
|
||||
private static Dictionary<string, WeakReference> cache = new Dictionary<string, WeakReference>();
|
||||
private string _regionPath;
|
||||
|
||||
private Dictionary<string, WeakReference> cache = new Dictionary<string, WeakReference>();
|
||||
|
||||
private RegionFileCache() {
|
||||
public RegionFileCache (string path) {
|
||||
_regionPath = path;
|
||||
|
||||
if (!Directory.Exists(_regionPath)) {
|
||||
throw new DirectoryNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
public static RegionFile GetRegionFile(string basePath, string fileName) {
|
||||
string regionDir = Path.Combine(basePath, "region");
|
||||
string file = Path.Combine(regionDir, fileName);
|
||||
public RegionFile GetRegionFile (string fileName) {
|
||||
//string regionDir = basePath; // Path.Combine(basePath, "region");
|
||||
string file = Path.Combine(_regionPath, fileName);
|
||||
|
||||
RegionFile rf = null;
|
||||
if (cache.ContainsKey(file)) {
|
||||
|
@ -27,10 +34,6 @@ namespace NBToolkit
|
|||
return rf;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(regionDir)) {
|
||||
Directory.CreateDirectory(regionDir);
|
||||
}
|
||||
|
||||
if (cache.Count >= MAX_CACHE_SIZE) {
|
||||
RegionFileCache.Clear();
|
||||
}
|
||||
|
@ -40,32 +43,11 @@ namespace NBToolkit
|
|||
return reg;
|
||||
}
|
||||
|
||||
public static RegionFile GetRegionFile (string basePath, int chunkX, int chunkZ)
|
||||
public RegionFile GetRegionFile (int chunkX, int chunkZ)
|
||||
{
|
||||
string regionDir = Path.Combine(basePath, "region");
|
||||
string fileName = Path.Combine(regionDir, "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mcr");
|
||||
string fileName = "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mcr";
|
||||
|
||||
return GetRegionFile(basePath, fileName);
|
||||
}
|
||||
|
||||
public static string[] GetRegionFileList (string basePath)
|
||||
{
|
||||
string regionDir = Path.Combine(basePath, "region");
|
||||
|
||||
if (!Directory.Exists(regionDir)) {
|
||||
Directory.CreateDirectory(regionDir);
|
||||
}
|
||||
|
||||
string[] files = Directory.GetFiles(regionDir);
|
||||
List<string> valid = new List<string>();
|
||||
|
||||
foreach (string file in files) {
|
||||
if (System.Text.RegularExpressions.Regex.IsMatch(file, "r\\.-?[0-9]+\\.-?[0-9]+\\.mcr$")) {
|
||||
valid.Add(Path.GetFileName(file));
|
||||
}
|
||||
}
|
||||
|
||||
return valid.ToArray();
|
||||
return GetRegionFile(fileName);
|
||||
}
|
||||
|
||||
public static void Clear() {
|
||||
|
@ -92,5 +74,5 @@ namespace NBToolkit
|
|||
RegionFile r = GetRegionFile(basePath, chunkX, chunkZ);
|
||||
return r.GetChunkDataOutputStream(chunkX & 31, chunkZ & 31);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
28
NBToolkit/NBToolkit/RegionKey.cs
Normal file
28
NBToolkit/NBToolkit/RegionKey.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class RegionKey : IEquatable<RegionKey>
|
||||
{
|
||||
protected int rx;
|
||||
protected int rz;
|
||||
|
||||
public RegionKey (int _rx, int _rz)
|
||||
{
|
||||
rx = _rx;
|
||||
rz = _rz;
|
||||
}
|
||||
|
||||
public bool Equals (RegionKey ck)
|
||||
{
|
||||
return this.rx == ck.rx && this.rz == ck.rz;
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return rx ^ rz;
|
||||
}
|
||||
}
|
||||
}
|
47
NBToolkit/NBToolkit/RegionManager.cs
Normal file
47
NBToolkit/NBToolkit/RegionManager.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
public class RegionManager
|
||||
{
|
||||
protected string _regionPath;
|
||||
|
||||
protected Dictionary<RegionKey, Region> _cache;
|
||||
|
||||
public RegionManager (string regionDir)
|
||||
{
|
||||
_regionPath = regionDir;
|
||||
_cache = new Dictionary<RegionKey, Region>();
|
||||
}
|
||||
|
||||
public Region GetRegion (int rx, int rz)
|
||||
{
|
||||
RegionKey k = new RegionKey(rx, rz);
|
||||
Region r;
|
||||
|
||||
if (_cache.TryGetValue(k, out r) == false) {
|
||||
r = new Region(this, rx, rz);
|
||||
_cache.Add(k, r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public Region GetRegion (string filename)
|
||||
{
|
||||
int rx, rz;
|
||||
if (!Region.ParseFileName(filename, out rx, out rz)) {
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
return GetRegion(rx, rz);
|
||||
}
|
||||
|
||||
public string GetRegionPath ()
|
||||
{
|
||||
return _regionPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,24 @@ namespace NBToolkit
|
|||
public int? OPT_DATA = null;
|
||||
public double? OPT_PROB = null;
|
||||
|
||||
// Block coordinate conditions
|
||||
public int? BL_X_GE = null;
|
||||
public int? BL_X_LE = null;
|
||||
public int? BL_Y_GE = null;
|
||||
public int? BL_Y_LE = null;
|
||||
public int? BL_Z_GE = null;
|
||||
public int? BL_Z_LE = null;
|
||||
|
||||
// Neighbor conditions
|
||||
public int? OPT_NEIGHBOR = null;
|
||||
public int? OPT_NEIGHBOR_SIDE = null;
|
||||
public int? OPT_NEIGHBOR_E = null;
|
||||
public int? OPT_NEIGHBOR_W = null;
|
||||
public int? OPT_NEIGHBOR_N = null;
|
||||
public int? OPT_NEIGHBOR_S = null;
|
||||
public int? OPT_NEIGHBOR_T = null;
|
||||
public int? OPT_NEIGHBOR_B = null;
|
||||
|
||||
public ReplaceOptions (string[] args) : base(args)
|
||||
{
|
||||
filterOpt = new OptionSet()
|
||||
|
@ -30,6 +48,40 @@ namespace NBToolkit
|
|||
v => { OPT_PROB = Convert.ToDouble(v);
|
||||
OPT_PROB = Math.Max((double)OPT_PROB, 0.0);
|
||||
OPT_PROB = Math.Min((double)OPT_PROB, 1.0); } },
|
||||
{ "bxa=", "Update blocks with X-coord equal to or above {VAL}",
|
||||
v => BL_X_GE = Convert.ToInt32(v) },
|
||||
{ "bxb=", "Update blocks with X-coord equal to or below {VAL}",
|
||||
v => BL_X_LE = Convert.ToInt32(v) },
|
||||
{ "bxr=", "Update blocks with X-coord between {0:V1} and {1:V2} [inclusive]",
|
||||
(v1, v2) => { BL_X_GE = Convert.ToInt32(v1); BL_X_LE = Convert.ToInt32(v2); } },
|
||||
{ "bya=", "Update blocks with Y-coord equal to or above {VAL}",
|
||||
v => BL_Y_GE = Convert.ToInt32(v) },
|
||||
{ "byb=", "Update blocks with Y-coord equal to or below {VAL}",
|
||||
v => BL_Y_LE = Convert.ToInt32(v) },
|
||||
{ "byr=", "Update blocks with Y-coord between {0:V1} and {1:V2} [inclusive]",
|
||||
(v1, v2) => { BL_Y_GE = Convert.ToInt32(v1); BL_Y_LE = Convert.ToInt32(v2); } },
|
||||
{ "bza=", "Update blocks with Z-coord equal to or above {VAL}",
|
||||
v => BL_Z_GE = Convert.ToInt32(v) },
|
||||
{ "bzb=", "Update blocks with Z-coord equal to or below {VAL}",
|
||||
v => BL_Z_LE = Convert.ToInt32(v) },
|
||||
{ "bzr=", "Update blocks with Z-coord between {0:V1} and {1:V2} [inclusive]",
|
||||
(v1, v2) => { BL_Z_GE = Convert.ToInt32(v1); BL_Z_LE = Convert.ToInt32(v2); } },
|
||||
{ "nb=", "Update blocks that have block type {ID} as any neighbor",
|
||||
v => OPT_NEIGHBOR = Convert.ToInt32(v) % 256 },
|
||||
{ "nbs=", "Update blocks that have block type {ID} as any x/z neighbor",
|
||||
v => OPT_NEIGHBOR_SIDE = Convert.ToInt32(v) % 256 },
|
||||
{ "nbxa=", "Update blocks that have block type {ID} as their south neighbor",
|
||||
v => OPT_NEIGHBOR_S = Convert.ToInt32(v) % 256 },
|
||||
{ "nbxb=", "Update blocks that have block type {ID} as their north neighbor",
|
||||
v => OPT_NEIGHBOR_N = Convert.ToInt32(v) % 256 },
|
||||
{ "nbya=", "Update blocks that have block type {ID} as their top neighbor",
|
||||
v => OPT_NEIGHBOR_T = Convert.ToInt32(v) % 256 },
|
||||
{ "nbyb=", "Update blocks that have block type {ID} as their bottom neighbor",
|
||||
v => OPT_NEIGHBOR_B = Convert.ToInt32(v) % 256 },
|
||||
{ "nbza=", "Update blocks that have block type {ID} as their west neighbor",
|
||||
v => OPT_NEIGHBOR_W = Convert.ToInt32(v) % 256 },
|
||||
{ "nbzb=", "Update blocks that have block type {ID} as their east neighbor",
|
||||
v => OPT_NEIGHBOR_E = Convert.ToInt32(v) % 256 },
|
||||
};
|
||||
|
||||
filterOpt.Parse(args);
|
||||
|
@ -94,15 +146,74 @@ namespace NBToolkit
|
|||
return;
|
||||
}
|
||||
|
||||
NBT_Tag xPos = level.findTagByName("xPos");
|
||||
NBT_Tag zPos = level.findTagByName("zPos");
|
||||
if (xPos == null || zPos == null || xPos.type != NBT_Type.TAG_INT || zPos.type != NBT_Type.TAG_INT) {
|
||||
return;
|
||||
}
|
||||
|
||||
int xBase = xPos.value.toInt().data * 16;
|
||||
int zBase = zPos.value.toInt().data * 16;
|
||||
|
||||
NBT_ByteArray blocks_ary = blocks.value.toByteArray();
|
||||
NBT_ByteArray data_ary = data.value.toByteArray();
|
||||
|
||||
// Determine X range
|
||||
int xmin = 0;
|
||||
int xmax = 15;
|
||||
|
||||
if (opt.BL_X_GE != null) {
|
||||
xmin = (int)opt.BL_X_GE - xBase;
|
||||
}
|
||||
if (opt.BL_X_LE != null) {
|
||||
xmax = (int)opt.BL_X_LE - xBase;
|
||||
}
|
||||
|
||||
xmin = (xmin < 0) ? 0 : xmin;
|
||||
xmax = (xmin > 15) ? 15 : xmax;
|
||||
|
||||
if (xmin > 15 || xmax < 0 || xmin > xmax) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine Y range
|
||||
int ymin = 0;
|
||||
int ymax = 127;
|
||||
|
||||
if (opt.BL_Y_GE != null) {
|
||||
ymin = (int)opt.BL_Y_GE;
|
||||
}
|
||||
if (opt.BL_Y_LE != null) {
|
||||
ymax = (int)opt.BL_Y_LE;
|
||||
}
|
||||
|
||||
if (ymin > ymax) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine X range
|
||||
int zmin = 0;
|
||||
int zmax = 15;
|
||||
|
||||
if (opt.BL_Z_GE != null) {
|
||||
zmin = (int)opt.BL_Z_GE - zBase;
|
||||
}
|
||||
if (opt.BL_Z_LE != null) {
|
||||
zmax = (int)opt.BL_Z_LE - zBase;
|
||||
}
|
||||
|
||||
zmin = (zmin < 0) ? 0 : zmin;
|
||||
zmax = (zmin > 15) ? 15 : zmax;
|
||||
|
||||
if (zmin > 15 || zmax < 0 || zmin > zmax) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process Chunk
|
||||
for (int y = ymin; y <= ymax; y++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = xmin; x <= xmax; x++) {
|
||||
for (int z = zmin; z <= zmax; z++) {
|
||||
// Probability test
|
||||
if (opt.OPT_PROB != null) {
|
||||
double c = rand.NextDouble();
|
||||
if (c > opt.OPT_PROB) {
|
||||
|
@ -110,6 +221,7 @@ namespace NBToolkit
|
|||
}
|
||||
}
|
||||
|
||||
// Attempt to replace block
|
||||
int index = BlockIndex(x, y, z);
|
||||
if (blocks_ary.data[index] == opt.OPT_BEFORE) {
|
||||
blocks_ary.data[index] = (byte)opt.OPT_AFTER;
|
||||
|
|
|
@ -27,12 +27,6 @@ namespace NBToolkit
|
|||
public int? CH_Z_GE = null;
|
||||
public int? CH_Z_LE = null;
|
||||
|
||||
// Block coordinate conditions
|
||||
public int? BL_X_GE = null;
|
||||
public int? BL_X_LE = null;
|
||||
public int? BL_Z_GE = null;
|
||||
public int? BL_Z_LE = null;
|
||||
|
||||
public TKOptions (string[] args)
|
||||
{
|
||||
commonOpt = new OptionSet()
|
||||
|
@ -83,7 +77,7 @@ namespace NBToolkit
|
|||
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();
|
||||
this.PrintUsage();
|
||||
|
|
40
NBToolkit/NBToolkit/World.cs
Normal file
40
NBToolkit/NBToolkit/World.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
class World
|
||||
{
|
||||
protected RegionManager _regionMan;
|
||||
protected ChunkManager _chunkMan;
|
||||
protected BlockManager _blockMan;
|
||||
|
||||
protected string _worldPath;
|
||||
|
||||
public World (string world)
|
||||
{
|
||||
_worldPath = world;
|
||||
|
||||
_regionMan = new RegionManager(Path.Combine(world, "region"));
|
||||
_chunkMan = new ChunkManager(_regionMan);
|
||||
_blockMan = new BlockManager(_chunkMan);
|
||||
}
|
||||
|
||||
public RegionManager GetRegionManager ()
|
||||
{
|
||||
return _regionMan;
|
||||
}
|
||||
|
||||
public ChunkManager GetChunkManager ()
|
||||
{
|
||||
return _chunkMan;
|
||||
}
|
||||
|
||||
public BlockManager GetBlockManager ()
|
||||
{
|
||||
return _blockMan;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue