forked from mirrors/NBTExplorer
Level info class added, additional work to World. Player, Level, and World implementations are still rough around the edges.
This commit is contained in:
parent
382399c141
commit
134e979323
9 changed files with 292 additions and 17 deletions
|
@ -49,4 +49,9 @@ namespace Substrate
|
||||||
bool SetTileEntity (int lx, int ly, int lz, TileEntity te);
|
bool SetTileEntity (int lx, int ly, int lz, TileEntity te);
|
||||||
bool ClearTileEntity (int lx, int ly, int lz);
|
bool ClearTileEntity (int lx, int ly, int lz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IBlockManager : IBlockContainer
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Substrate
|
||||||
bool SetBlock (int x, int y, int z, Block block);
|
bool SetBlock (int x, int y, int z, Block block);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public class BlockManager : IBlockContainer
|
public class BlockManager : IBlockManager
|
||||||
{
|
{
|
||||||
public const int MIN_X = -32000000;
|
public const int MIN_X = -32000000;
|
||||||
public const int MAX_X = 32000000;
|
public const int MAX_X = 32000000;
|
||||||
|
@ -36,11 +36,11 @@ namespace Substrate
|
||||||
|
|
||||||
public static bool EnforceDataLimits = true;
|
public static bool EnforceDataLimits = true;
|
||||||
|
|
||||||
protected ChunkManager _chunkMan;
|
protected IChunkManager _chunkMan;
|
||||||
|
|
||||||
protected ChunkRef _cache;
|
protected ChunkRef _cache;
|
||||||
|
|
||||||
public BlockManager (ChunkManager cm)
|
public BlockManager (IChunkManager cm)
|
||||||
{
|
{
|
||||||
_chunkMan = cm;
|
_chunkMan = cm;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Substrate
|
||||||
{
|
{
|
||||||
using NBT;
|
using NBT;
|
||||||
|
|
||||||
public class ChunkFileManager : IChunkContainer, IChunkCache
|
public class ChunkFileManager : IChunkManager, IChunkCache
|
||||||
{
|
{
|
||||||
protected string _mapPath;
|
protected string _mapPath;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ namespace Substrate
|
||||||
protected NBT_Tree GetChunkTree (int cx, int cz)
|
protected NBT_Tree GetChunkTree (int cx, int cz)
|
||||||
{
|
{
|
||||||
ChunkFile cf = GetChunkFile(cx, cz);
|
ChunkFile cf = GetChunkFile(cx, cz);
|
||||||
Stream nbtstr = cf.GetChunkDataInputStream();
|
Stream nbtstr = cf.GetDataInputStream();
|
||||||
if (nbtstr == null) {
|
if (nbtstr == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ namespace Substrate
|
||||||
protected bool SaveChunkTree (int cx, int cz, NBT_Tree tree)
|
protected bool SaveChunkTree (int cx, int cz, NBT_Tree tree)
|
||||||
{
|
{
|
||||||
ChunkFile cf = GetChunkFile(cx, cz);
|
ChunkFile cf = GetChunkFile(cx, cz);
|
||||||
Stream zipstr = cf.GetChunkDataOutputStream();
|
Stream zipstr = cf.GetDataOutputStream();
|
||||||
if (zipstr == null) {
|
if (zipstr == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ namespace Substrate
|
||||||
|
|
||||||
protected Stream GetChunkOutStream (int cx, int cz)
|
protected Stream GetChunkOutStream (int cx, int cz)
|
||||||
{
|
{
|
||||||
return new ChunkFile(_mapPath, cx, cz).GetChunkDataOutputStream();
|
return new ChunkFile(_mapPath, cx, cz).GetDataOutputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IChunkContainer Members
|
#region IChunkContainer Members
|
||||||
|
|
|
@ -47,4 +47,9 @@ namespace Substrate
|
||||||
int Save ();
|
int Save ();
|
||||||
bool SaveChunk (Chunk chunk);
|
bool SaveChunk (Chunk chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IChunkManager : IChunkContainer
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.Text;
|
||||||
namespace Substrate
|
namespace Substrate
|
||||||
{
|
{
|
||||||
|
|
||||||
public class ChunkManager : IChunkContainer, IChunkCache, IEnumerable<ChunkRef>
|
public class ChunkManager : IChunkManager, IChunkCache, IEnumerable<ChunkRef>
|
||||||
{
|
{
|
||||||
public const int REGION_XLEN = 32;
|
public const int REGION_XLEN = 32;
|
||||||
public const int REGION_ZLEN = 32;
|
public const int REGION_ZLEN = 32;
|
||||||
|
|
232
Substrate/SubstrateCS/Source/Level.cs
Normal file
232
Substrate/SubstrateCS/Source/Level.cs
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Substrate
|
||||||
|
{
|
||||||
|
using NBT;
|
||||||
|
using Utility;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
public class Level : INBTObject<Level>, ICopyable<Level>
|
||||||
|
{
|
||||||
|
public static NBTCompoundNode LevelSchema = new NBTCompoundNode()
|
||||||
|
{
|
||||||
|
new NBTCompoundNode("Data")
|
||||||
|
{
|
||||||
|
new NBTScalerNode("Time", NBT_Type.TAG_LONG),
|
||||||
|
new NBTScalerNode("LastPlayed", NBT_Type.TAG_LONG),
|
||||||
|
new NBTCompoundNode("Player", Player.PlayerSchema),
|
||||||
|
new NBTScalerNode("SpawnX", NBT_Type.TAG_INT),
|
||||||
|
new NBTScalerNode("SpawnY", NBT_Type.TAG_INT),
|
||||||
|
new NBTScalerNode("SpawnZ", NBT_Type.TAG_INT),
|
||||||
|
new NBTScalerNode("SizeOnDisk", NBT_Type.TAG_LONG),
|
||||||
|
new NBTScalerNode("RandomSeed", NBT_Type.TAG_LONG),
|
||||||
|
new NBTScalerNode("Version", NBT_Type.TAG_INT, NBTOptions.OPTIONAL),
|
||||||
|
new NBTScalerNode("LevelName", NBT_Type.TAG_STRING, NBTOptions.OPTIONAL),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
private World _world;
|
||||||
|
|
||||||
|
private long _time;
|
||||||
|
private long _lastPlayed;
|
||||||
|
|
||||||
|
private Player _player;
|
||||||
|
|
||||||
|
private int _spawnX;
|
||||||
|
private int _spawnY;
|
||||||
|
private int _spawnZ;
|
||||||
|
|
||||||
|
private long _sizeOnDisk;
|
||||||
|
private long _randomSeed;
|
||||||
|
private int? _version;
|
||||||
|
private string _name;
|
||||||
|
|
||||||
|
public long Time
|
||||||
|
{
|
||||||
|
get { return _time; }
|
||||||
|
set { _time = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long LastPlayed
|
||||||
|
{
|
||||||
|
get { return _lastPlayed; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player Player
|
||||||
|
{
|
||||||
|
get { return _player; }
|
||||||
|
set { _player = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SpawnX
|
||||||
|
{
|
||||||
|
get { return _spawnX; }
|
||||||
|
set { _spawnX = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SpawnY
|
||||||
|
{
|
||||||
|
get { return _spawnY; }
|
||||||
|
set { _spawnY = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SpawnZ
|
||||||
|
{
|
||||||
|
get { return _spawnZ; }
|
||||||
|
set { _spawnZ = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long SizeOnDisk
|
||||||
|
{
|
||||||
|
get { return _sizeOnDisk; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long RandomSeed
|
||||||
|
{
|
||||||
|
get { return _randomSeed; }
|
||||||
|
set { _randomSeed = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Version
|
||||||
|
{
|
||||||
|
get { return _version ?? 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string LevelName
|
||||||
|
{
|
||||||
|
get { return _name; }
|
||||||
|
set { _name = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Level (World world)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Level (Level p)
|
||||||
|
{
|
||||||
|
_world = p._world;
|
||||||
|
|
||||||
|
_time = p._time;
|
||||||
|
_lastPlayed = p._lastPlayed;
|
||||||
|
_spawnX = p._spawnX;
|
||||||
|
_spawnY = p._spawnY;
|
||||||
|
_spawnZ = p._spawnZ;
|
||||||
|
_sizeOnDisk = p._sizeOnDisk;
|
||||||
|
_randomSeed = p._randomSeed;
|
||||||
|
_version = p._version;
|
||||||
|
_name = p._name;
|
||||||
|
|
||||||
|
if (p._player != null) {
|
||||||
|
_player = p._player.Copy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Save ()
|
||||||
|
{
|
||||||
|
if (_world == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NBTFile nf = new NBTFile(Path.Combine(_world.WorldPath, "level.dat"));
|
||||||
|
Stream zipstr = nf.GetDataOutputStream();
|
||||||
|
if (zipstr == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
new NBT_Tree(BuildTree() as NBT_Compound).WriteTo(zipstr);
|
||||||
|
zipstr.Close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region INBTObject<Player> Members
|
||||||
|
|
||||||
|
public virtual Level LoadTree (NBT_Value tree)
|
||||||
|
{
|
||||||
|
NBT_Compound dtree = tree as NBT_Compound;
|
||||||
|
if (dtree == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
NBT_Compound ctree = dtree["Data"].ToNBTCompound();
|
||||||
|
|
||||||
|
_time = ctree["Time"].ToNBTLong();
|
||||||
|
_lastPlayed = ctree["LastPlayed"].ToNBTLong();
|
||||||
|
|
||||||
|
_player = new Player().LoadTree(ctree["Player"]);
|
||||||
|
|
||||||
|
_spawnX = ctree["SpawnX"].ToNBTInt();
|
||||||
|
_spawnY = ctree["SpawnY"].ToNBTInt();
|
||||||
|
_spawnZ = ctree["SpawnZ"].ToNBTInt();
|
||||||
|
|
||||||
|
_sizeOnDisk = ctree["SizeOnDisk"].ToNBTLong();
|
||||||
|
_randomSeed = ctree["RandomSeed"].ToNBTLong();
|
||||||
|
|
||||||
|
if (ctree.ContainsKey("Version")) {
|
||||||
|
_version = ctree["Version"].ToNBTInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctree.ContainsKey("LevelName")) {
|
||||||
|
_name = ctree["LevelName"].ToNBTString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Level LoadTreeSafe (NBT_Value tree)
|
||||||
|
{
|
||||||
|
if (!ValidateTree(tree)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadTree(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual NBT_Value BuildTree ()
|
||||||
|
{
|
||||||
|
NBT_Compound data = new NBT_Compound();
|
||||||
|
data["Time"] = new NBT_Long(_time);
|
||||||
|
data["LastPlayed"] = new NBT_Long(_lastPlayed);
|
||||||
|
data["Player"] = _player.BuildTree();
|
||||||
|
data["SpawnX"] = new NBT_Int(_spawnX);
|
||||||
|
data["SpawnY"] = new NBT_Int(_spawnY);
|
||||||
|
data["SpawnZ"] = new NBT_Int(_spawnZ);
|
||||||
|
data["SizeOnDisk"] = new NBT_Long(_sizeOnDisk);
|
||||||
|
data["RandomSeed"] = new NBT_Long(_randomSeed);
|
||||||
|
|
||||||
|
if (_version != null) {
|
||||||
|
data["Version"] = new NBT_Int(_version ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_name != null) {
|
||||||
|
data["LevelName"] = new NBT_String(_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
NBT_Compound tree = new NBT_Compound();
|
||||||
|
tree.Add("Data", data);
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool ValidateTree (NBT_Value tree)
|
||||||
|
{
|
||||||
|
return new NBTVerifier(tree, LevelSchema).Verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region ICopyable<Entity> Members
|
||||||
|
|
||||||
|
public virtual Level Copy ()
|
||||||
|
{
|
||||||
|
return new Level(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ namespace Substrate
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream GetChunkDataInputStream ()
|
public Stream GetDataInputStream ()
|
||||||
{
|
{
|
||||||
FileStream fstr = new FileStream(_filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
FileStream fstr = new FileStream(_filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ namespace Substrate
|
||||||
return new GZipStream(new MemoryStream(data), CompressionMode.Decompress);
|
return new GZipStream(new MemoryStream(data), CompressionMode.Decompress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream GetChunkDataOutputStream ()
|
public Stream GetDataOutputStream ()
|
||||||
{
|
{
|
||||||
return new ZlibStream(new NBTBuffer(this), CompressionMode.Compress);
|
return new ZlibStream(new NBTBuffer(this), CompressionMode.Compress);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Substrate
|
||||||
protected NBT_Tree GetPlayerTree (string name)
|
protected NBT_Tree GetPlayerTree (string name)
|
||||||
{
|
{
|
||||||
PlayerFile pf = GetPlayerFile(name);
|
PlayerFile pf = GetPlayerFile(name);
|
||||||
Stream nbtstr = pf.GetChunkDataInputStream();
|
Stream nbtstr = pf.GetDataInputStream();
|
||||||
if (nbtstr == null) {
|
if (nbtstr == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ namespace Substrate
|
||||||
protected bool SavePlayerTree (string name, NBT_Tree tree)
|
protected bool SavePlayerTree (string name, NBT_Tree tree)
|
||||||
{
|
{
|
||||||
PlayerFile pf = GetPlayerFile(name);
|
PlayerFile pf = GetPlayerFile(name);
|
||||||
Stream zipstr = pf.GetChunkDataOutputStream();
|
Stream zipstr = pf.GetDataOutputStream();
|
||||||
if (zipstr == null) {
|
if (zipstr == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,25 +5,45 @@ using System.IO;
|
||||||
|
|
||||||
namespace Substrate
|
namespace Substrate
|
||||||
{
|
{
|
||||||
|
using NBT;
|
||||||
|
|
||||||
public class World
|
public class World
|
||||||
{
|
{
|
||||||
protected RegionManager _regionMan;
|
protected RegionManager _regionMan;
|
||||||
protected ChunkManager _chunkMan;
|
protected IChunkManager _chunkMan;
|
||||||
protected BlockManager _blockMan;
|
protected IBlockManager _blockMan;
|
||||||
protected PlayerManager _playerMan;
|
protected PlayerManager _playerMan;
|
||||||
|
|
||||||
protected string _worldPath;
|
protected string _worldPath;
|
||||||
|
|
||||||
|
protected Level _level;
|
||||||
|
|
||||||
|
public string WorldPath
|
||||||
|
{
|
||||||
|
get { return _worldPath; }
|
||||||
|
}
|
||||||
|
|
||||||
public World (string world)
|
public World (string world)
|
||||||
{
|
{
|
||||||
_worldPath = world;
|
_worldPath = world;
|
||||||
|
|
||||||
|
if (!File.Exists(Path.Combine(_worldPath, "level.dat"))) {
|
||||||
|
throw new Exception("Could not locate level.dat");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LoadLevel()) {
|
||||||
|
throw new Exception("Failed to load level.dat");
|
||||||
|
}
|
||||||
|
|
||||||
if (Directory.Exists(Path.Combine(world, "region"))) {
|
if (Directory.Exists(Path.Combine(world, "region"))) {
|
||||||
_regionMan = new RegionManager(Path.Combine(world, "region"));
|
_regionMan = new RegionManager(Path.Combine(world, "region"));
|
||||||
_chunkMan = new ChunkManager(_regionMan);
|
_chunkMan = new ChunkManager(_regionMan);
|
||||||
}
|
}
|
||||||
else if (Directory.Exists(Path.Combine(world, "0"))) {
|
else if (Directory.Exists(Path.Combine(world, "0"))) {
|
||||||
//_chunkMan = new ChunkFileManager(world);
|
_chunkMan = new ChunkFileManager(world);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Exception("Could not locate any world data");
|
||||||
}
|
}
|
||||||
|
|
||||||
_blockMan = new BlockManager(_chunkMan);
|
_blockMan = new BlockManager(_chunkMan);
|
||||||
|
@ -33,17 +53,30 @@ namespace Substrate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected bool LoadLevel ()
|
||||||
|
{
|
||||||
|
NBTFile nf = new NBTFile(Path.Combine(_worldPath, "level.dat"));
|
||||||
|
Stream nbtstr = nf.GetDataInputStream();
|
||||||
|
if (nbtstr == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_level = new Level(this).LoadTreeSafe(new NBT_Tree(nbtstr).Root);
|
||||||
|
|
||||||
|
return _level != null;
|
||||||
|
}
|
||||||
|
|
||||||
public RegionManager GetRegionManager ()
|
public RegionManager GetRegionManager ()
|
||||||
{
|
{
|
||||||
return _regionMan;
|
return _regionMan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkManager GetChunkManager ()
|
public IChunkManager GetChunkManager ()
|
||||||
{
|
{
|
||||||
return _chunkMan;
|
return _chunkMan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockManager GetBlockManager ()
|
public IBlockManager GetBlockManager ()
|
||||||
{
|
{
|
||||||
return _blockMan;
|
return _blockMan;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue