forked from mirrors/NBTExplorer
Split out generic NBTFile loader, added support for player IO and a PlayerManager.
This commit is contained in:
parent
0860bae2bc
commit
382399c141
7 changed files with 290 additions and 60 deletions
|
@ -6,16 +6,15 @@ using Ionic.Zlib;
|
|||
|
||||
namespace Substrate
|
||||
{
|
||||
class ChunkFile
|
||||
public class ChunkFile : NBTFile
|
||||
{
|
||||
private string _filename;
|
||||
|
||||
public ChunkFile (string path)
|
||||
: base(path)
|
||||
{
|
||||
_filename = path;
|
||||
}
|
||||
|
||||
public ChunkFile (string path, int cx, int cz)
|
||||
: base("")
|
||||
{
|
||||
string cx64 = Base64(cx);
|
||||
string cz64 = Base64(cz);
|
||||
|
@ -33,55 +32,5 @@ namespace Substrate
|
|||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Substrate
|
|||
{
|
||||
using NBT;
|
||||
|
||||
class ChunkFileManager : IChunkContainer, IChunkCache
|
||||
public class ChunkFileManager : IChunkContainer, IChunkCache
|
||||
{
|
||||
protected string _mapPath;
|
||||
|
||||
|
|
70
Substrate/SubstrateCS/Source/NBTFile.cs
Normal file
70
Substrate/SubstrateCS/Source/NBTFile.cs
Normal file
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Ionic.Zlib;
|
||||
|
||||
namespace Substrate
|
||||
{
|
||||
using NBT;
|
||||
|
||||
public class NBTFile
|
||||
{
|
||||
protected string _filename;
|
||||
|
||||
public NBTFile (string path)
|
||||
{
|
||||
_filename = path;
|
||||
}
|
||||
|
||||
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 NBTBuffer(this), CompressionMode.Compress);
|
||||
}
|
||||
|
||||
class NBTBuffer : MemoryStream
|
||||
{
|
||||
private NBTFile file;
|
||||
|
||||
public NBTBuffer (NBTFile c)
|
||||
: base(8096)
|
||||
{
|
||||
this.file = c;
|
||||
}
|
||||
|
||||
public override void Close ()
|
||||
{
|
||||
FileStream fstr = new FileStream(file._filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
fstr.Write(this.GetBuffer(), 0, (int)this.Length);
|
||||
fstr.Close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace Substrate
|
|||
using NBT;
|
||||
using Utility;
|
||||
|
||||
public class Player : UntypedEntity, INBTObject<Player>, ICopyable<Player>
|
||||
public class Player : UntypedEntity, INBTObject<Player>, ICopyable<Player>, IItemContainer
|
||||
{
|
||||
public static readonly NBTCompoundNode PlayerSchema = UTBaseSchema.MergeInto(new NBTCompoundNode("")
|
||||
{
|
||||
|
@ -21,6 +21,8 @@ namespace Substrate
|
|||
new NBTScalerNode("SpawnZ", NBT_Type.TAG_INT, NBTOptions.OPTIONAL),
|
||||
});
|
||||
|
||||
private const int _CAPACITY = 105;
|
||||
|
||||
private int _dimension;
|
||||
private byte _sleeping;
|
||||
private short _sleepTimer;
|
||||
|
@ -28,19 +30,69 @@ namespace Substrate
|
|||
private int? _spawnY;
|
||||
private int? _spawnZ;
|
||||
|
||||
private string? _world;
|
||||
private string _world;
|
||||
|
||||
private ItemCollection _inventory;
|
||||
|
||||
public int Dimension
|
||||
{
|
||||
get { return _dimension; }
|
||||
set { _dimension = value; }
|
||||
}
|
||||
|
||||
public bool IsSleeping
|
||||
{
|
||||
get { return _sleeping == 1; }
|
||||
set { _sleeping = (byte)(value ? 1 : 0); }
|
||||
}
|
||||
|
||||
public int SleepTimer
|
||||
{
|
||||
get { return _sleepTimer; }
|
||||
set { _sleepTimer = (short)value; }
|
||||
}
|
||||
|
||||
public int SpawnX
|
||||
{
|
||||
get { return _spawnX ?? 0; }
|
||||
set { _spawnX = value; }
|
||||
}
|
||||
|
||||
public int SpawnY
|
||||
{
|
||||
get { return _spawnY ?? 0; }
|
||||
set { _spawnY = value; }
|
||||
}
|
||||
|
||||
public int SpawnZ
|
||||
{
|
||||
get { return _spawnZ ?? 0; }
|
||||
set { _spawnZ = value; }
|
||||
}
|
||||
|
||||
public string World
|
||||
{
|
||||
get { return _world; }
|
||||
set { _world = value; }
|
||||
}
|
||||
|
||||
public Player ()
|
||||
: base()
|
||||
{
|
||||
_inventory = new ItemCollection(_CAPACITY);
|
||||
}
|
||||
|
||||
public Player (Player p)
|
||||
: base(p)
|
||||
{
|
||||
|
||||
_dimension = p._dimension;
|
||||
_sleeping = p._sleeping;
|
||||
_sleepTimer = p._sleepTimer;
|
||||
_spawnX = p._spawnX;
|
||||
_spawnY = p._spawnY;
|
||||
_spawnZ = p._spawnZ;
|
||||
_world = p._world;
|
||||
_inventory = p._inventory.Copy();
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,6 +105,26 @@ namespace Substrate
|
|||
return null;
|
||||
}
|
||||
|
||||
_dimension = ctree["Dimension"].ToNBTInt();
|
||||
_sleeping = ctree["Sleeping"].ToNBTByte();
|
||||
_sleepTimer = ctree["SleepTimer"].ToNBTShort();
|
||||
|
||||
if (ctree.ContainsKey("SpawnX")) {
|
||||
_spawnX = ctree["SpawnX"].ToNBTInt();
|
||||
}
|
||||
if (ctree.ContainsKey("SpawnY")) {
|
||||
_spawnY = ctree["SpawnY"].ToNBTInt();
|
||||
}
|
||||
if (ctree.ContainsKey("SpawnZ")) {
|
||||
_spawnZ = ctree["SpawnZ"].ToNBTInt();
|
||||
}
|
||||
|
||||
if (ctree.ContainsKey("World")) {
|
||||
_world = ctree["World"].ToNBTString();
|
||||
}
|
||||
|
||||
_inventory.LoadTree(ctree["Inventory"].ToNBTList());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -68,6 +140,21 @@ namespace Substrate
|
|||
public virtual new NBT_Value BuildTree ()
|
||||
{
|
||||
NBT_Compound tree = base.BuildTree() as NBT_Compound;
|
||||
tree["Dimension"] = new NBT_Int(_dimension);
|
||||
tree["Sleeping"] = new NBT_Byte(_sleeping);
|
||||
tree["SleepTimer"] = new NBT_Short(_sleepTimer);
|
||||
|
||||
if (_spawnX != null && _spawnY != null && _spawnZ != null) {
|
||||
tree["SpawnX"] = new NBT_Int(_spawnX ?? 0);
|
||||
tree["SpawnY"] = new NBT_Int(_spawnY ?? 0);
|
||||
tree["SpawnZ"] = new NBT_Int(_spawnZ ?? 0);
|
||||
}
|
||||
|
||||
if (_world != null) {
|
||||
tree["World"] = new NBT_String(_world);
|
||||
}
|
||||
|
||||
tree["Inventory"] = _inventory.BuildTree();
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
@ -88,5 +175,15 @@ namespace Substrate
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region IItemContainer Members
|
||||
|
||||
public ItemCollection Items
|
||||
{
|
||||
get { return _inventory; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
23
Substrate/SubstrateCS/Source/PlayerFile.cs
Normal file
23
Substrate/SubstrateCS/Source/PlayerFile.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Ionic.Zlib;
|
||||
|
||||
namespace Substrate
|
||||
{
|
||||
public class PlayerFile : NBTFile
|
||||
{
|
||||
public PlayerFile (string path)
|
||||
: base(path)
|
||||
{
|
||||
}
|
||||
|
||||
public PlayerFile (string path, string name)
|
||||
: base("")
|
||||
{
|
||||
string file = name + ".dat";
|
||||
_filename = Path.Combine(path, file);
|
||||
}
|
||||
}
|
||||
}
|
75
Substrate/SubstrateCS/Source/PlayerManager.cs
Normal file
75
Substrate/SubstrateCS/Source/PlayerManager.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Substrate
|
||||
{
|
||||
using NBT;
|
||||
|
||||
public class PlayerManager
|
||||
{
|
||||
protected string _playerPath;
|
||||
|
||||
public PlayerManager (string playerDir)
|
||||
{
|
||||
_playerPath = playerDir;
|
||||
}
|
||||
|
||||
protected PlayerFile GetPlayerFile (string name)
|
||||
{
|
||||
return new PlayerFile(_playerPath, name);
|
||||
}
|
||||
|
||||
protected NBT_Tree GetPlayerTree (string name)
|
||||
{
|
||||
PlayerFile pf = GetPlayerFile(name);
|
||||
Stream nbtstr = pf.GetChunkDataInputStream();
|
||||
if (nbtstr == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NBT_Tree(nbtstr);
|
||||
}
|
||||
|
||||
protected bool SavePlayerTree (string name, NBT_Tree tree)
|
||||
{
|
||||
PlayerFile pf = GetPlayerFile(name);
|
||||
Stream zipstr = pf.GetChunkDataOutputStream();
|
||||
if (zipstr == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tree.WriteTo(zipstr);
|
||||
zipstr.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Player GetPlayer (string name)
|
||||
{
|
||||
if (!PlayerExists(name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Player().LoadTreeSafe(GetPlayerTree(name).Root);
|
||||
}
|
||||
|
||||
public bool SetPlayer (string name, Player player)
|
||||
{
|
||||
return SavePlayerTree(name, new NBT_Tree(player.BuildTree() as NBT_Compound));
|
||||
}
|
||||
|
||||
public bool PlayerExists (string name)
|
||||
{
|
||||
return new PlayerFile(_playerPath, name).Exists();
|
||||
}
|
||||
|
||||
public bool DeletePlayer (string name)
|
||||
{
|
||||
new PlayerFile(_playerPath, name).Delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ namespace Substrate
|
|||
protected RegionManager _regionMan;
|
||||
protected ChunkManager _chunkMan;
|
||||
protected BlockManager _blockMan;
|
||||
protected PlayerManager _playerMan;
|
||||
|
||||
protected string _worldPath;
|
||||
|
||||
|
@ -17,9 +18,19 @@ namespace Substrate
|
|||
{
|
||||
_worldPath = world;
|
||||
|
||||
_regionMan = new RegionManager(Path.Combine(world, "region"));
|
||||
_chunkMan = new ChunkManager(_regionMan);
|
||||
if (Directory.Exists(Path.Combine(world, "region"))) {
|
||||
_regionMan = new RegionManager(Path.Combine(world, "region"));
|
||||
_chunkMan = new ChunkManager(_regionMan);
|
||||
}
|
||||
else if (Directory.Exists(Path.Combine(world, "0"))) {
|
||||
//_chunkMan = new ChunkFileManager(world);
|
||||
}
|
||||
|
||||
_blockMan = new BlockManager(_chunkMan);
|
||||
|
||||
if (Directory.Exists(Path.Combine(world, "players"))) {
|
||||
_playerMan = new PlayerManager(Path.Combine(world, "players"));
|
||||
}
|
||||
}
|
||||
|
||||
public RegionManager GetRegionManager ()
|
||||
|
@ -36,5 +47,10 @@ namespace Substrate
|
|||
{
|
||||
return _blockMan;
|
||||
}
|
||||
|
||||
public PlayerManager GetPlayerManager ()
|
||||
{
|
||||
return _playerMan;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue