forked from mirrors/NBTExplorer
Properly handling Tile Entity consistency for block modification. Added building default trees from NBT schema, JSON Serializer for trees, start of a dumping command for nbtoolkit, and untested Chunk File support for Alpha maps.
This commit is contained in:
parent
895178d5d3
commit
d89a892623
18 changed files with 663 additions and 77 deletions
34
NBToolkit/NBToolkit/Dump.cs
Normal file
34
NBToolkit/NBToolkit/Dump.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NBToolkit
|
||||
{
|
||||
using Map;
|
||||
using Map.NBT;
|
||||
using System.IO;
|
||||
|
||||
class Dump : TKFilter
|
||||
{
|
||||
private ReplaceOptions opt;
|
||||
|
||||
public Dump (ReplaceOptions o)
|
||||
{
|
||||
opt = o;
|
||||
}
|
||||
|
||||
public override void Run ()
|
||||
{
|
||||
World world = new World(opt.OPT_WORLD);
|
||||
|
||||
StreamWriter fstr = new StreamWriter("json.txt", false);
|
||||
|
||||
foreach (ChunkRef chunk in new FilteredChunkList(world.GetChunkManager(), opt.GetChunkFilter())) {
|
||||
string s = JSONSerializer.Serialize(chunk.GetChunkRef().Tree.Root["Level"].ToNBTCompound()["TileEntities"]);
|
||||
fstr.Write(s);
|
||||
}
|
||||
|
||||
fstr.Close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -434,7 +434,7 @@ namespace NBToolkit.Map
|
|||
|
||||
Dispenser.SetTileEntity("Trap", TileEntity.TrapSchema);
|
||||
NoteBlock.SetTileEntity("Music", TileEntity.MusicSchema);
|
||||
MonsterSpawner.SetTileEntity("MonsterSpawner", TileEntity.MonsterSpawnerSchema);
|
||||
MonsterSpawner.SetTileEntity("MonsterSpawner", TileEntity.MobSpawnerSchema);
|
||||
Chest.SetTileEntity("Chest", TileEntity.ChestSchema);
|
||||
Furnace.SetTileEntity("Furnace", TileEntity.FurnaceSchema);
|
||||
BurningFurnace.SetTileEntity("Furnace", TileEntity.FurnaceSchema);
|
||||
|
|
|
@ -32,6 +32,11 @@ namespace NBToolkit.Map
|
|||
get { return _cz; }
|
||||
}
|
||||
|
||||
public NBT_Tree Tree
|
||||
{
|
||||
get { return _tree; }
|
||||
}
|
||||
|
||||
public bool IsTerrainPopulated
|
||||
{
|
||||
get { return _tree.Root["Level"].ToNBTCompound()["TerrainPopulated"].ToNBTByte() == 1; }
|
||||
|
@ -64,6 +69,17 @@ namespace NBToolkit.Map
|
|||
_entities = level["Entities"] as NBT_List;
|
||||
_tileEntities = level["TileEntities"] as NBT_List;
|
||||
|
||||
// List-type patch up
|
||||
if (_entities.Count == 0) {
|
||||
level["Entities"] = new NBT_List(NBT_Type.TAG_COMPOUND);
|
||||
_entities = level["Entities"] as NBT_List;
|
||||
}
|
||||
|
||||
if (_tileEntities.Count == 0) {
|
||||
level["TileEntities"] = new NBT_List(NBT_Type.TAG_COMPOUND);
|
||||
_tileEntities = level["TileEntities"] as NBT_List;
|
||||
}
|
||||
|
||||
_cx = level["xPos"].ToNBTInt();
|
||||
_cz = level["zPos"].ToNBTInt();
|
||||
}
|
||||
|
@ -201,9 +217,18 @@ namespace NBToolkit.Map
|
|||
|
||||
// Update tile entities
|
||||
|
||||
if (BlockInfo.SchemaTable[_blocks[index]] != null &&
|
||||
BlockInfo.SchemaTable[_blocks[index]] != BlockInfo.SchemaTable[id]) {
|
||||
ClearTileEntity(lx, ly, lz);
|
||||
if (BlockInfo.SchemaTable[_blocks[index]] != BlockInfo.SchemaTable[id]) {
|
||||
if (BlockInfo.SchemaTable[_blocks[index]] != null) {
|
||||
ClearTileEntity(lx, ly, lz);
|
||||
}
|
||||
|
||||
if (BlockInfo.SchemaTable[id] != null) {
|
||||
TileEntity te = new TileEntity(BlockInfo.SchemaTable[id]);
|
||||
te.X = BlockGlobalX(lx);
|
||||
te.Y = BlockGlobalY(ly);
|
||||
te.Z = BlockGlobalZ(lz);
|
||||
_tileEntities.Add(te.Root);
|
||||
}
|
||||
}
|
||||
|
||||
// Update height map
|
||||
|
@ -301,10 +326,14 @@ namespace NBToolkit.Map
|
|||
|
||||
public TileEntity GetTileEntity (int lx, int ly, int lz)
|
||||
{
|
||||
int x = BlockGlobalX(lx);
|
||||
int y = BlockGlobalY(ly);
|
||||
int z = BlockGlobalZ(lz);
|
||||
|
||||
foreach (NBT_Compound te in _tileEntities) {
|
||||
if (te["x"].ToNBTInt().Data == lx &&
|
||||
te["y"].ToNBTInt().Data == ly &&
|
||||
te["z"].ToNBTInt().Data == lz) {
|
||||
if (te["x"].ToNBTInt().Data == x &&
|
||||
te["y"].ToNBTInt().Data == y &&
|
||||
te["z"].ToNBTInt().Data == z) {
|
||||
return new TileEntity(te);
|
||||
}
|
||||
}
|
||||
|
@ -327,23 +356,18 @@ namespace NBToolkit.Map
|
|||
|
||||
ClearTileEntity(lx, ly, lz);
|
||||
|
||||
int x = BlockX(lx);
|
||||
int y = BlockY(ly);
|
||||
int z = BlockZ(lz);
|
||||
|
||||
if (!te.LocatedAt(x, y, z)) {
|
||||
te = te.Copy();
|
||||
te.Relocate(x, y, z);
|
||||
}
|
||||
te.X = BlockGlobalX(lx);
|
||||
te.Y = BlockGlobalY(ly);
|
||||
te.Z = BlockGlobalZ(lz);
|
||||
|
||||
_tileEntities.Add(te.Root);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ClearTileEntity (int x, int y, int z)
|
||||
public bool ClearTileEntity (int lx, int ly, int lz)
|
||||
{
|
||||
TileEntity te = GetTileEntity(x, y, z);
|
||||
TileEntity te = GetTileEntity(lx, ly, lz);
|
||||
if (te == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -365,21 +389,6 @@ namespace NBToolkit.Map
|
|||
}
|
||||
}
|
||||
|
||||
protected int BlockX (int lx)
|
||||
{
|
||||
return _cx * BlockManager.CHUNK_XLEN + lx;
|
||||
}
|
||||
|
||||
protected int BlockY (int ly)
|
||||
{
|
||||
return ly;
|
||||
}
|
||||
|
||||
protected int BlockZ (int lz)
|
||||
{
|
||||
return _cz * BlockManager.CHUNK_ZLEN + lz;
|
||||
}
|
||||
|
||||
#region ICopyable<Chunk> Members
|
||||
|
||||
public Chunk Copy ()
|
||||
|
|
87
NBToolkit/NBToolkit/Map/ChunkFile.cs
Normal file
87
NBToolkit/NBToolkit/Map/ChunkFile.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Ionic.Zlib;
|
||||
|
||||
namespace NBToolkit.Map
|
||||
{
|
||||
class ChunkFile
|
||||
{
|
||||
private string _filename;
|
||||
|
||||
public ChunkFile (string path)
|
||||
{
|
||||
_filename = path;
|
||||
}
|
||||
|
||||
public ChunkFile (string path, int cx, int cz)
|
||||
{
|
||||
string cx64 = Base64(cx);
|
||||
string cz64 = Base64(cz);
|
||||
string file = "c." + cx64 + "." + cz64 + ".dat";
|
||||
|
||||
string dir1 = Base64(cx % 64);
|
||||
string dir2 = Base64(cz % 64);
|
||||
|
||||
_filename = Path.Combine(path, dir1);
|
||||
_filename = Path.Combine(_filename, dir2);
|
||||
_filename = Path.Combine(_filename, file);
|
||||
}
|
||||
|
||||
private string Base64 (int val)
|
||||
{
|
||||
return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(val.ToString()));
|
||||
}
|
||||
|
||||
public bool Exists ()
|
||||
{
|
||||
return File.Exists(_filename);
|
||||
}
|
||||
|
||||
public bool Delete ()
|
||||
{
|
||||
File.Delete(_filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
public Stream GetChunkDataInputStream ()
|
||||
{
|
||||
FileStream fstr = new FileStream(_filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
long length = fstr.Seek(0, SeekOrigin.End);
|
||||
fstr.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
byte[] data = new byte[length];
|
||||
fstr.Read(data, 0, data.Length);
|
||||
|
||||
fstr.Close();
|
||||
|
||||
return new GZipStream(new MemoryStream(data), CompressionMode.Decompress);
|
||||
}
|
||||
|
||||
public Stream GetChunkDataOutputStream ()
|
||||
{
|
||||
return new ZlibStream(new ChunkBuffer(this), CompressionMode.Compress);
|
||||
}
|
||||
|
||||
class ChunkBuffer : MemoryStream
|
||||
{
|
||||
private ChunkFile region;
|
||||
|
||||
public ChunkBuffer (ChunkFile c)
|
||||
: base(8096)
|
||||
{
|
||||
this.region = c;
|
||||
}
|
||||
|
||||
public override void Close ()
|
||||
{
|
||||
FileStream fstr = new FileStream(region._filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
fstr.Write(this.GetBuffer(), 0, (int)this.Length);
|
||||
fstr.Close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
188
NBToolkit/NBToolkit/Map/ChunkFileManager.cs
Normal file
188
NBToolkit/NBToolkit/Map/ChunkFileManager.cs
Normal file
|
@ -0,0 +1,188 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace NBToolkit.Map
|
||||
{
|
||||
using NBT;
|
||||
|
||||
class ChunkFileManager : IChunkContainer, IChunkCache
|
||||
{
|
||||
protected string _mapPath;
|
||||
|
||||
protected Dictionary<ChunkKey, WeakReference> _cache;
|
||||
protected Dictionary<ChunkKey, ChunkRef> _dirty;
|
||||
|
||||
public ChunkFileManager (string mapDir)
|
||||
{
|
||||
_mapPath = mapDir;
|
||||
_cache = new Dictionary<ChunkKey, WeakReference>();
|
||||
_dirty = new Dictionary<ChunkKey, ChunkRef>();
|
||||
}
|
||||
|
||||
protected ChunkFile GetChunkFile (int cx, int cz)
|
||||
{
|
||||
return new ChunkFile(_mapPath, cx, cz);
|
||||
}
|
||||
|
||||
protected NBT_Tree GetChunkTree (int cx, int cz)
|
||||
{
|
||||
ChunkFile cf = GetChunkFile(cx, cz);
|
||||
Stream nbtstr = cf.GetChunkDataInputStream();
|
||||
if (nbtstr == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NBT_Tree(nbtstr);
|
||||
}
|
||||
|
||||
protected bool SaveChunkTree (int cx, int cz, NBT_Tree tree)
|
||||
{
|
||||
ChunkFile cf = GetChunkFile(cx, cz);
|
||||
Stream zipstr = cf.GetChunkDataOutputStream();
|
||||
if (zipstr == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tree.WriteTo(zipstr);
|
||||
zipstr.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Stream GetChunkOutStream (int cx, int cz)
|
||||
{
|
||||
return new ChunkFile(_mapPath, cx, cz).GetChunkDataOutputStream();
|
||||
}
|
||||
|
||||
#region IChunkContainer Members
|
||||
|
||||
public int ChunkGlobalX (int cx)
|
||||
{
|
||||
return cx;
|
||||
}
|
||||
|
||||
public int ChunkGlobalZ (int cz)
|
||||
{
|
||||
return cz;
|
||||
}
|
||||
|
||||
public int ChunkLocalX (int cx)
|
||||
{
|
||||
return cx;
|
||||
}
|
||||
|
||||
public int ChunkLocalZ (int cz)
|
||||
{
|
||||
return cz;
|
||||
}
|
||||
|
||||
public Chunk GetChunk (int cx, int cz)
|
||||
{
|
||||
if (!ChunkExists(cx, cz)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Chunk(GetChunkTree(cx, cz));
|
||||
}
|
||||
|
||||
public ChunkRef GetChunkRef (int cx, int cz)
|
||||
{
|
||||
ChunkKey k = new ChunkKey(cx, cz);
|
||||
|
||||
ChunkRef c = null;
|
||||
|
||||
WeakReference chunkref = null;
|
||||
if (_cache.TryGetValue(k, out chunkref)) {
|
||||
c = chunkref.Target as ChunkRef;
|
||||
}
|
||||
else {
|
||||
_cache.Add(k, new WeakReference(null));
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
return c;
|
||||
}
|
||||
|
||||
try {
|
||||
c = new ChunkRef(this, this, cx, cz);
|
||||
_cache[k].Target = c;
|
||||
return c;
|
||||
}
|
||||
catch (MissingChunkException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ChunkExists (int cx, int cz)
|
||||
{
|
||||
return new ChunkFile(_mapPath, cx, cz).Exists();
|
||||
}
|
||||
|
||||
public bool DeleteChunk (int cx, int cz)
|
||||
{
|
||||
new ChunkFile(_mapPath, cx, cz).Delete();
|
||||
|
||||
ChunkKey k = new ChunkKey(cx, cz);
|
||||
_cache.Remove(k);
|
||||
_dirty.Remove(k);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Save ()
|
||||
{
|
||||
int saved = 0;
|
||||
foreach (ChunkRef c in _dirty.Values) {
|
||||
int cx = ChunkGlobalX(c.X);
|
||||
int cz = ChunkGlobalZ(c.Z);
|
||||
|
||||
if (c.Save(GetChunkOutStream(cx, cz))) {
|
||||
saved++;
|
||||
}
|
||||
}
|
||||
|
||||
_dirty.Clear();
|
||||
return saved;
|
||||
}
|
||||
|
||||
public bool SaveChunk (Chunk chunk)
|
||||
{
|
||||
return chunk.Save(GetChunkOutStream(ChunkGlobalX(chunk.X), ChunkGlobalZ(chunk.Z)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IChunkCache Members
|
||||
|
||||
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, GetChunkRef(cx, cz));
|
||||
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
|
||||
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace NBToolkit.Map
|
||||
{
|
||||
|
@ -23,7 +24,7 @@ namespace NBToolkit.Map
|
|||
public interface IChunkCache
|
||||
{
|
||||
bool MarkChunkDirty (ChunkRef chunk);
|
||||
bool MarkChunkClean (int cx, int cz);
|
||||
bool MarkChunkClean (ChunkRef chunk);
|
||||
}
|
||||
|
||||
public interface IChunkContainer
|
||||
|
|
|
@ -93,15 +93,19 @@ namespace NBToolkit.Map
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool MarkChunkClean (int cx, int cz)
|
||||
public bool MarkChunkClean (ChunkRef chunk)
|
||||
{
|
||||
Region r = GetRegion(cx, cz);
|
||||
Region r = GetRegion(chunk.X, chunk.Z);
|
||||
if (r == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RegionKey k = new RegionKey(r.X, r.Z);
|
||||
return _dirty.Remove(k);
|
||||
_dirty.Remove(k);
|
||||
|
||||
r.MarkChunkClean(chunk);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Save ()
|
||||
|
|
164
NBToolkit/NBToolkit/Map/NBT/JSONSerializer.cs
Normal file
164
NBToolkit/NBToolkit/Map/NBT/JSONSerializer.cs
Normal file
|
@ -0,0 +1,164 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NBToolkit.Map.NBT
|
||||
{
|
||||
class JSONSerializer
|
||||
{
|
||||
public static string Serialize (NBT_Value tag)
|
||||
{
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
if (tag.GetNBTType() == NBT_Type.TAG_COMPOUND) {
|
||||
SerializeCompound(tag as NBT_Compound, str, 0);
|
||||
}
|
||||
else if (tag.GetNBTType() == NBT_Type.TAG_LIST) {
|
||||
SerializeList(tag as NBT_List, str, 0);
|
||||
}
|
||||
else {
|
||||
SerializeScaler(tag, str);
|
||||
}
|
||||
|
||||
str.AppendLine();
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
private static void SerializeCompound (NBT_Compound tag, StringBuilder str, int level)
|
||||
{
|
||||
if (tag.Count == 0) {
|
||||
str.Append("{ }");
|
||||
return;
|
||||
}
|
||||
|
||||
str.AppendLine();
|
||||
AddLine(str, "{", level);
|
||||
|
||||
IEnumerator<KeyValuePair<string, NBT_Value>> en = tag.GetEnumerator();
|
||||
bool first = true;
|
||||
while (en.MoveNext()) {
|
||||
if (!first) {
|
||||
str.Append(",");
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
KeyValuePair<string, NBT_Value> item = en.Current;
|
||||
Add(str, "\"" + item.Key + "\": ", level + 1);
|
||||
|
||||
if (item.Value.GetNBTType() == NBT_Type.TAG_COMPOUND) {
|
||||
SerializeCompound(item.Value as NBT_Compound, str, level + 1);
|
||||
}
|
||||
else if (item.Value.GetNBTType() == NBT_Type.TAG_LIST) {
|
||||
SerializeList(item.Value as NBT_List, str, level + 1);
|
||||
}
|
||||
else {
|
||||
SerializeScaler(item.Value, str);
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
str.AppendLine();
|
||||
Add(str, "}", level);
|
||||
}
|
||||
|
||||
private static void SerializeList (NBT_List tag, StringBuilder str, int level)
|
||||
{
|
||||
if (tag.Count == 0) {
|
||||
str.Append("[ ]");
|
||||
return;
|
||||
}
|
||||
|
||||
str.AppendLine();
|
||||
AddLine(str, "[", level);
|
||||
|
||||
IEnumerator<NBT_Value> en = tag.GetEnumerator();
|
||||
bool first = true;
|
||||
while (en.MoveNext()) {
|
||||
if (!first) {
|
||||
str.Append(",");
|
||||
}
|
||||
|
||||
NBT_Value item = en.Current;
|
||||
|
||||
if (item.GetNBTType() == NBT_Type.TAG_COMPOUND) {
|
||||
SerializeCompound(item as NBT_Compound, str, level + 1);
|
||||
}
|
||||
else if (item.GetNBTType() == NBT_Type.TAG_LIST) {
|
||||
SerializeList(item as NBT_List, str, level + 1);
|
||||
}
|
||||
else {
|
||||
if (!first) {
|
||||
str.AppendLine();
|
||||
}
|
||||
Indent(str, level + 1);
|
||||
SerializeScaler(item, str);
|
||||
}
|
||||
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
str.AppendLine();
|
||||
Add(str, "]", level);
|
||||
}
|
||||
|
||||
private static void SerializeScaler (NBT_Value tag, StringBuilder str)
|
||||
{
|
||||
NBT_Type type = tag.GetNBTType();
|
||||
switch (tag.GetNBTType()) {
|
||||
case NBT_Type.TAG_STRING:
|
||||
str.Append("\"" + tag.ToNBTString().Data + "\"");
|
||||
break;
|
||||
|
||||
case NBT_Type.TAG_BYTE:
|
||||
str.Append(tag.ToNBTByte().Data);
|
||||
break;
|
||||
|
||||
case NBT_Type.TAG_SHORT:
|
||||
str.Append(tag.ToNBTShort().Data);
|
||||
break;
|
||||
|
||||
case NBT_Type.TAG_INT:
|
||||
str.Append(tag.ToNBTInt().Data);
|
||||
break;
|
||||
|
||||
case NBT_Type.TAG_LONG:
|
||||
str.Append(tag.ToNBTLong().Data);
|
||||
break;
|
||||
|
||||
case NBT_Type.TAG_FLOAT:
|
||||
str.Append(tag.ToNBTFloat().Data);
|
||||
break;
|
||||
|
||||
case NBT_Type.TAG_DOUBLE:
|
||||
str.Append(tag.ToNBTDouble().Data);
|
||||
break;
|
||||
|
||||
case NBT_Type.TAG_BYTE_ARRAY:
|
||||
str.Append("null");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddLine (StringBuilder str, string line, int level)
|
||||
{
|
||||
Indent(str, level);
|
||||
str.AppendLine(line);
|
||||
}
|
||||
|
||||
private static void Add (StringBuilder str, string line, int level)
|
||||
{
|
||||
Indent(str, level);
|
||||
str.Append(line);
|
||||
}
|
||||
|
||||
private static void Indent (StringBuilder str, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
str.Append("\t");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,11 @@ namespace NBToolkit.Map.NBT
|
|||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public virtual NBT_Value BuildDefaultTree ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class NBTScalerNode : NBTSchemaNode
|
||||
|
@ -33,11 +38,39 @@ namespace NBToolkit.Map.NBT
|
|||
{
|
||||
_type = type;
|
||||
}
|
||||
|
||||
public override NBT_Value BuildDefaultTree ()
|
||||
{
|
||||
switch (_type) {
|
||||
case NBT_Type.TAG_STRING:
|
||||
return new NBT_String();
|
||||
|
||||
case NBT_Type.TAG_BYTE:
|
||||
return new NBT_Byte();
|
||||
|
||||
case NBT_Type.TAG_SHORT:
|
||||
return new NBT_Short();
|
||||
|
||||
case NBT_Type.TAG_INT:
|
||||
return new NBT_Int();
|
||||
|
||||
case NBT_Type.TAG_LONG:
|
||||
return new NBT_Long();
|
||||
|
||||
case NBT_Type.TAG_FLOAT:
|
||||
return new NBT_Float();
|
||||
|
||||
case NBT_Type.TAG_DOUBLE:
|
||||
return new NBT_Double();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class NBTStringNode : NBTSchemaNode
|
||||
{
|
||||
private string _value;
|
||||
private string _value = "";
|
||||
private int _length;
|
||||
|
||||
public int Length
|
||||
|
@ -61,6 +94,15 @@ namespace NBToolkit.Map.NBT
|
|||
{
|
||||
_length = length;
|
||||
}
|
||||
|
||||
public override NBT_Value BuildDefaultTree ()
|
||||
{
|
||||
if (_value.Length > 0) {
|
||||
return new NBT_String(_value);
|
||||
}
|
||||
|
||||
return new NBT_String();
|
||||
}
|
||||
}
|
||||
|
||||
public class NBTArrayNode : NBTSchemaNode
|
||||
|
@ -83,6 +125,11 @@ namespace NBToolkit.Map.NBT
|
|||
{
|
||||
_length = length;
|
||||
}
|
||||
|
||||
public override NBT_Value BuildDefaultTree ()
|
||||
{
|
||||
return new NBT_ByteArray(new byte[_length]);
|
||||
}
|
||||
}
|
||||
|
||||
public class NBTListNode : NBTSchemaNode
|
||||
|
@ -112,13 +159,6 @@ namespace NBToolkit.Map.NBT
|
|||
_type = type;
|
||||
}
|
||||
|
||||
public NBTListNode (string name, NBT_Type type, int length)
|
||||
: base(name)
|
||||
{
|
||||
_type = type;
|
||||
_length = length;
|
||||
}
|
||||
|
||||
public NBTListNode (string name, NBT_Type type, NBTSchemaNode subschema)
|
||||
: base(name)
|
||||
{
|
||||
|
@ -133,6 +173,20 @@ namespace NBToolkit.Map.NBT
|
|||
_length = length;
|
||||
_subschema = subschema;
|
||||
}
|
||||
|
||||
public override NBT_Value BuildDefaultTree ()
|
||||
{
|
||||
if (_length == 0) {
|
||||
return new NBT_List(_type);
|
||||
}
|
||||
|
||||
NBT_List list = new NBT_List(_type);
|
||||
for (int i = 0; i < _length; i++) {
|
||||
list.Add(_subschema.BuildDefaultTree());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public class NBTCompoundNode : NBTSchemaNode, ICollection<NBTSchemaNode>
|
||||
|
@ -213,12 +267,22 @@ namespace NBToolkit.Map.NBT
|
|||
foreach (NBTSchemaNode node in _subnodes) {
|
||||
NBTSchemaNode f = tree._subnodes.Find(n => n.Name == node.Name);
|
||||
if (f != null) {
|
||||
tree.Remove(f);
|
||||
continue;
|
||||
}
|
||||
tree.Add(node);
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
public override NBT_Value BuildDefaultTree ()
|
||||
{
|
||||
NBT_Compound list = new NBT_Compound();
|
||||
foreach (NBTSchemaNode node in _subnodes) {
|
||||
list[node.Name] = node.BuildDefaultTree();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -319,7 +319,7 @@ namespace NBToolkit.Map.NBT {
|
|||
|
||||
public class NBT_String : NBT_Value
|
||||
{
|
||||
private string _data = null;
|
||||
private string _data = "";
|
||||
|
||||
override public NBT_String ToNBTString () { return this; }
|
||||
override public NBT_Type GetNBTType () { return NBT_Type.TAG_STRING; }
|
||||
|
|
|
@ -175,6 +175,11 @@ namespace NBToolkit.Map.NBT
|
|||
return false;
|
||||
}
|
||||
|
||||
// Patch up empty lists
|
||||
//if (schema.Length == 0) {
|
||||
// tag = new NBT_List(schema.Type);
|
||||
//}
|
||||
|
||||
bool pass = true;
|
||||
|
||||
// If a subschema is set, test all items in list against it
|
||||
|
|
|
@ -215,22 +215,22 @@ namespace NBToolkit.Map
|
|||
|
||||
public int ChunkGlobalX (int cx)
|
||||
{
|
||||
return cx;
|
||||
return _rx * ChunkManager.REGION_XLEN + cx;
|
||||
}
|
||||
|
||||
public int ChunkGlobalZ (int cz)
|
||||
{
|
||||
return cz;
|
||||
return _rz * ChunkManager.REGION_ZLEN + cz;
|
||||
}
|
||||
|
||||
public int ChunkLocalX (int cx)
|
||||
{
|
||||
return cx & ChunkManager.REGION_XMASK;
|
||||
return cx;
|
||||
}
|
||||
|
||||
public int ChunkLocalZ (int cz)
|
||||
{
|
||||
return cz & ChunkManager.REGION_ZMASK;
|
||||
return cz;
|
||||
}
|
||||
|
||||
public Chunk GetChunk (int lcx, int lcz)
|
||||
|
@ -277,8 +277,8 @@ namespace NBToolkit.Map
|
|||
{
|
||||
int saved = 0;
|
||||
foreach (ChunkRef c in _dirty.Values) {
|
||||
int lcx = ChunkLocalX(c.X);
|
||||
int lcz = ChunkLocalZ(c.Z);
|
||||
int lcx = c.LocalX;
|
||||
int lcz = c.LocalZ;
|
||||
|
||||
if (!ChunkExists(lcx, lcz)) {
|
||||
throw new MissingChunkException();
|
||||
|
@ -316,8 +316,11 @@ namespace NBToolkit.Map
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool MarkChunkClean (int lcx, int lcz)
|
||||
public bool MarkChunkClean (ChunkRef chunk)
|
||||
{
|
||||
int lcx = chunk.LocalX;
|
||||
int lcz = chunk.LocalZ;
|
||||
|
||||
ChunkKey k = new ChunkKey(lcx, lcz);
|
||||
if (_dirty.ContainsKey(k)) {
|
||||
_dirty.Remove(k);
|
||||
|
|
|
@ -16,6 +16,29 @@ namespace NBToolkit.Map
|
|||
get { return _tree; }
|
||||
}
|
||||
|
||||
public string ID
|
||||
{
|
||||
get { return _tree["id"].ToNBTString(); }
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get { return _tree["x"].ToNBTInt(); }
|
||||
set { _tree["x"] = new NBT_Int(value); }
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get { return _tree["y"].ToNBTInt(); }
|
||||
set { _tree["y"] = new NBT_Int(value); }
|
||||
}
|
||||
|
||||
public int Z
|
||||
{
|
||||
get { return _tree["z"].ToNBTInt(); }
|
||||
set { _tree["z"] = new NBT_Int(value); }
|
||||
}
|
||||
|
||||
public TileEntity (string id)
|
||||
{
|
||||
_tree = new NBT_Compound();
|
||||
|
@ -30,6 +53,11 @@ namespace NBToolkit.Map
|
|||
_tree = tree;
|
||||
}
|
||||
|
||||
public TileEntity (NBTSchemaNode schema)
|
||||
{
|
||||
_tree = schema.BuildDefaultTree() as NBT_Compound;
|
||||
}
|
||||
|
||||
public bool Verify ()
|
||||
{
|
||||
NBTVerifier v = new NBTVerifier(Root, BaseSchema);
|
||||
|
@ -42,25 +70,11 @@ namespace NBToolkit.Map
|
|||
return v.Verify();
|
||||
}
|
||||
|
||||
public bool LocatedAt (int lx, int ly, int lz)
|
||||
public bool LocatedAt (int x, int y, int z)
|
||||
{
|
||||
return _tree["x"].ToNBTInt().Data == lx &&
|
||||
_tree["y"].ToNBTInt().Data == ly &&
|
||||
_tree["z"].ToNBTInt().Data == lz;
|
||||
}
|
||||
|
||||
public bool Relocate (int lx, int ly, int lz)
|
||||
{
|
||||
if (lx >= 0 && lx < BlockManager.CHUNK_XLEN &&
|
||||
ly >= 0 && ly < BlockManager.CHUNK_YLEN &&
|
||||
lz >= 0 && lz < BlockManager.CHUNK_ZLEN) {
|
||||
_tree["x"].ToNBTInt().Data = lx;
|
||||
_tree["y"].ToNBTInt().Data = ly;
|
||||
_tree["z"].ToNBTInt().Data = lz;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return _tree["x"].ToNBTInt().Data == x &&
|
||||
_tree["y"].ToNBTInt().Data == y &&
|
||||
_tree["z"].ToNBTInt().Data == z;
|
||||
}
|
||||
|
||||
#region Predefined Schemas
|
||||
|
@ -98,9 +112,9 @@ namespace NBToolkit.Map
|
|||
new NBTScalerNode("Text4", NBT_Type.TAG_STRING),
|
||||
});
|
||||
|
||||
public static readonly NBTCompoundNode MonsterSpawnerSchema = BaseSchema.MergeInto(new NBTCompoundNode("")
|
||||
public static readonly NBTCompoundNode MobSpawnerSchema = BaseSchema.MergeInto(new NBTCompoundNode("")
|
||||
{
|
||||
new NBTStringNode("id", "MonsterSpawner"),
|
||||
new NBTStringNode("id", "MobSpawner"),
|
||||
new NBTScalerNode("EntityId", NBT_Type.TAG_STRING),
|
||||
new NBTScalerNode("Delay", NBT_Type.TAG_SHORT),
|
||||
});
|
||||
|
|
|
@ -57,12 +57,17 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Dump.cs" />
|
||||
<Compile Include="Map\Block.cs" />
|
||||
<Compile Include="Map\BlockInfo.cs" />
|
||||
<Compile Include="Map\BlockInterface.cs" />
|
||||
<Compile Include="Map\BlockKey.cs" />
|
||||
<Compile Include="Map\BlockManager.cs" />
|
||||
<Compile Include="Map\BlockRef.cs" />
|
||||
<Compile Include="Map\Chunk.cs" />
|
||||
<Compile Include="Map\ChunkFile.cs" />
|
||||
<Compile Include="Map\ChunkFileManager.cs" />
|
||||
<Compile Include="Map\ChunkInterface.cs" />
|
||||
<Compile Include="Map\ChunkRef.cs" />
|
||||
<Compile Include="Map\ChunkEnumerator.cs" />
|
||||
<Compile Include="ChunkFilter.cs" />
|
||||
|
@ -71,6 +76,7 @@
|
|||
<Compile Include="Map\ChunkVerifier.cs" />
|
||||
<Compile Include="FilteredChunkEnumerator.cs" />
|
||||
<Compile Include="GenOres.cs" />
|
||||
<Compile Include="Map\NBT\JSONSerializer.cs" />
|
||||
<Compile Include="Map\TileEntity.cs" />
|
||||
<Compile Include="Map\Utility\Interface.cs" />
|
||||
<Compile Include="MathHelper.cs" />
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<StartArguments>oregen -w "F:\Minecraft\tps - Copy" -b 15 --chunkinclude=35 -vv --MaxDepth=75 --MinDepth=67</StartArguments>
|
||||
<StartArguments>replace -w "F:\Minecraft\tps - Copy" -b 61 -a 18 -vv</StartArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<StartArguments>oregen -w "F:\Minecraft\tps - Copy" -b 15 --chunkinclude=35 -vv --MaxDepth=75 --MinDepth=67</StartArguments>
|
||||
<StartArguments>replace -w "F:\Minecraft\tps - Copy" -b 61 -a 18 -vv</StartArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PublishUrlHistory>publish\</PublishUrlHistory>
|
||||
|
|
|
@ -199,7 +199,7 @@ namespace NBToolkit
|
|||
|
||||
ApplyChunk(world, chunk);
|
||||
|
||||
world.GetChunkManager().SaveDirtyChunks();
|
||||
world.GetChunkManager().Save();
|
||||
}
|
||||
|
||||
Console.WriteLine("Affected Chunks: " + affectedChunks);
|
||||
|
|
|
@ -36,6 +36,12 @@ namespace NBToolkit
|
|||
options.SetDefaults();
|
||||
filter.Run();
|
||||
}
|
||||
else if (args[0] == "dump") {
|
||||
ReplaceOptions options = new ReplaceOptions(args);
|
||||
Dump filter = new Dump(options);
|
||||
options.SetDefaults();
|
||||
filter.Run();
|
||||
}
|
||||
else if (args[0] == "help") {
|
||||
if (args.Length < 2) {
|
||||
args = new string[2] { "help", "help" };
|
||||
|
|
|
@ -157,7 +157,8 @@ namespace NBToolkit
|
|||
affectedChunks++;
|
||||
|
||||
ApplyChunk(world, chunk);
|
||||
chunk.Save();
|
||||
|
||||
world.GetChunkManager().Save();
|
||||
}
|
||||
|
||||
Console.WriteLine("Affected Chunks: " + affectedChunks);
|
||||
|
|
Loading…
Reference in a new issue