More major interface untangling. Introduction of generic IxContainer interfaces.

This commit is contained in:
Justin Aquadro 2011-04-03 05:22:12 +00:00
parent 3afb2238ef
commit 25f429f0cf
12 changed files with 778 additions and 138 deletions

View file

@ -49,7 +49,15 @@ namespace NBToolkit.Map
public int Data
{
get { return _data; }
set { _data = value; }
set
{
if (BlockManager.EnforceDataLimits && BlockInfo.BlockTable[_id] != null) {
if (!BlockInfo.BlockTable[_id].TestData(value)) {
return;
}
}
_data = value;
}
}
public int SkyLight

View file

@ -6,11 +6,95 @@ namespace NBToolkit.Map
{
using NBT;
public interface IBlockTileEntity
public enum BlockType
{
string TileEntityName { get; }
NBTCompoundNode TileEntitySchema { get; }
AIR = 0,
STONE = 1,
GRASS = 2,
DIRT = 3,
COBBLESTONE = 4,
WOOD_PLANK = 5,
SAPLING = 6,
BEDROCK = 7,
WATER = 8,
STATIONARY_WATER = 9,
LAVA = 10,
STATIONARY_LAVA = 11,
SAND = 12,
GRAVEL = 13,
GOLD_ORE = 14,
IRON_ORE = 15,
COAL_ORE = 16,
WOOD = 17,
LEAVES = 18,
SPONGE = 19,
GLASS = 20,
LAPIS_ORE = 21,
LAPIS_BLOCK = 22,
DISPENSER = 23,
SANDSTONE = 24,
NOTE_BLOCK = 25,
BED = 26,
WOOL = 35,
YELLOW_FLOWER = 37,
RED_ROSE = 38,
BROWN_MUSHROOM = 39,
RED_MUSHROOM = 40,
GOLD_BLOCK = 41,
IRON_BLOCK = 42,
DOUBLE_SLAB = 43,
SLAB = 44,
BRICK_BLOCK = 45,
TNT = 46,
BOOKSHELF = 47,
MOSS_STONE = 48,
OBSIDIAN = 49,
TORCH = 50,
FIRE = 51,
MONSTER_SPAWNER = 52,
WOOD_STAIRS = 53,
CHEST = 54,
REDSTONE_WIRE = 55,
DIAMOND_ORE = 56,
DIAMOND_BLOCK = 57,
CRAFTING_TABLE = 58,
CROPS = 59,
FARMLAND = 60,
FURNACE = 61,
BURNING_FURNACE = 62,
SIGN_POST = 63,
WOOD_DOOR = 64,
LADDER = 65,
RAILS = 66,
COBBLESTONE_STAIRS = 67,
WALL_SIGN = 68,
LEVER = 69,
STONE_PLATE = 70,
IRON_DOOR = 71,
WOOD_PLATE = 72,
REDSTONE_ORE = 73,
GLOWING_REDSTONE_ORE = 74,
REDSTONE_TORCH_OFF = 75,
REDSTONE_TORCH_ON = 76,
STONE_BUTTON = 77,
SNOW = 78,
ICE = 79,
SNOW_BLOCK = 80,
CACTUS = 81,
CLAY_BLOCK = 82,
SUGAR_CANE = 83,
JUKEBOX = 84,
FENCE = 85,
PUMPKIN = 86,
NETHERRACK = 87,
SOUL_SAND = 88,
GLOWSTONE_BLOCK = 89,
PORTAL = 90,
JACK_O_LANTERN = 91,
CAKE_BLOCK = 92,
REDSTONE_REPEATER_ON = 93,
REDSTONE_REPEATER_OFF = 94,
LOCKED_CHEST = 95,
}
public class BlockInfo
@ -43,11 +127,48 @@ namespace NBToolkit.Map
}
}
private class DataLimits
{
private int _low;
private int _high;
private int _bitmask;
public int Low
{
get { return _low; }
}
public int High
{
get { return _high; }
}
public int Bitmask
{
get { return _bitmask; }
}
public DataLimits (int low, int high, int bitmask)
{
_low = low;
_high = high;
_bitmask = bitmask;
}
public bool Test (int data)
{
int rdata = data & ~_bitmask;
return rdata >= _low && rdata <= _high;
}
}
private int _id = 0;
private string _name = "";
private int _opacity = MAX_OPACITY;
private int _luminance = MIN_LUMINANCE;
private DataLimits _dataLimits;
public static ItemCache<BlockInfo> BlockTable;
public static ItemCache<int> OpacityTable;
@ -103,16 +224,19 @@ namespace NBToolkit.Map
return this;
}
protected static NBTCompoundNode tileEntitySchema = new NBTCompoundNode("")
public BlockInfo SetDataLimits (int low, int high, int bitmask)
{
new NBTScalerNode("id", NBT_Type.TAG_STRING),
new NBTScalerNode("x", NBT_Type.TAG_INT),
new NBTScalerNode("y", NBT_Type.TAG_INT),
new NBTScalerNode("z", NBT_Type.TAG_INT),
};
_dataLimits = new DataLimits(low, high, bitmask);
return this;
}
public const int AIR = 0;
public const int FURNACE = 61;
public bool TestData (int data)
{
if (_dataLimits == null) {
return true;
}
return _dataLimits.Test(data);
}
public static BlockInfo Air;
public static BlockInfo Stone;
@ -276,7 +400,7 @@ namespace NBToolkit.Map
Lever = new BlockInfo(69, "Lever").SetOpacity(0);
StonePlate = new BlockInfo(70, "Stone Pressure Plate").SetOpacity(0);
IronDoor = new BlockInfo(71, "Iron Door").SetOpacity(0);
WoodPlank = new BlockInfo(72, "Wooden Pressure Plate").SetOpacity(0);
WoodPlate = new BlockInfo(72, "Wooden Pressure Plate").SetOpacity(0);
RedstoneOre = new BlockInfo(73, "Redstone Ore");
GlowRedstoneOre = new BlockInfo(74, "Glowing Redstone Ore").SetLuminance(9);
RedstoneTorch = new BlockInfo(75, "Redstone Torch (Off)").SetOpacity(0);
@ -306,6 +430,8 @@ namespace NBToolkit.Map
}
}
// Set Tile Entity Data
Dispenser.SetTileEntity("Trap", TileEntity.TrapSchema);
NoteBlock.SetTileEntity("Music", TileEntity.MusicSchema);
MonsterSpawner.SetTileEntity("MonsterSpawner", TileEntity.MonsterSpawnerSchema);
@ -314,6 +440,45 @@ namespace NBToolkit.Map
BurningFurnace.SetTileEntity("Furnace", TileEntity.FurnaceSchema);
SignPost.SetTileEntity("Sign", TileEntity.SignSchema);
WallSign.SetTileEntity("Sign", TileEntity.SignSchema);
// Set Data Limits
Wood.SetDataLimits(0, 2, 0);
Leaves.SetDataLimits(0, 2, 0);
Jukebox.SetDataLimits(0, 2, 0);
Sapling.SetDataLimits(0, 15, 0);
Cactus.SetDataLimits(0, 15, 0);
SugarCane.SetDataLimits(0, 15, 0);
Water.SetDataLimits(0, 7, 0x8);
Lava.SetDataLimits(0, 7, 0x8);
Crops.SetDataLimits(0, 7, 0);
Wool.SetDataLimits(0, 15, 0);
Torch.SetDataLimits(1, 5, 0);
RedstoneTorch.SetDataLimits(0, 5, 0);
RedstoneTorchOn.SetDataLimits(0, 5, 0);
Rails.SetDataLimits(0, 9, 0);
Ladder.SetDataLimits(2, 5, 0);
WoodStairs.SetDataLimits(0, 3, 0);
CobbleStairs.SetDataLimits(0, 3, 0);
Lever.SetDataLimits(0, 6, 0x8);
WoodDoor.SetDataLimits(0, 3, 0xC);
IronDoor.SetDataLimits(0, 3, 0xC);
StoneButton.SetDataLimits(1, 4, 0x8);
SignPost.SetDataLimits(0, 15, 0);
WallSign.SetDataLimits(2, 5, 0);
Furnace.SetDataLimits(2, 5, 0);
BurningFurnace.SetDataLimits(2, 5, 0);
Dispenser.SetDataLimits(2, 5, 0);
Pumpkin.SetDataLimits(0, 3, 0);
JackOLantern.SetDataLimits(0, 3, 0);
StonePlate.SetDataLimits(0, 0, 0x1);
WoodPlate.SetDataLimits(0, 0, 0x1);
Slab.SetDataLimits(0, 3, 0);
DoubleSlab.SetDataLimits(0, 3, 0);
Cactus.SetDataLimits(0, 5, 0);
Bed.SetDataLimits(0, 3, 0x8);
RedstoneRepeater.SetDataLimits(0, 0, 0xF);
RedstoneRepeaterOn.SetDataLimits(0, 0, 0xF);
}
}

View file

@ -4,7 +4,16 @@ using System.Text;
namespace NBToolkit.Map
{
public class BlockManager
/*public interface IBlockManager : IBlockContainer
{
Block GetBlock (int x, int y, int z);
BlockRef GetBlockRef (int x, int y, int z);
BlockInfo GetBlockInfo (int x, int y, int z);
bool SetBlock (int x, int y, int z, Block block);
}*/
public class BlockManager : IBlockContainer
{
public const int MIN_X = -32000000;
public const int MAX_X = 32000000;
@ -25,6 +34,8 @@ namespace NBToolkit.Map
public const int CHUNK_YMASK = 0x7F;
public const int CHUNK_ZMASK = 0xF;
public static bool EnforceDataLimits = true;
protected ChunkManager _chunkMan;
protected ChunkRef _cache;
@ -39,6 +50,36 @@ namespace NBToolkit.Map
_chunkMan = bm._chunkMan;
}
public int GlobalX (int x)
{
return x;
}
public int GlobalY (int y)
{
return y;
}
public int GlobalZ (int z)
{
return z;
}
public int LocalX (int x)
{
return x & CHUNK_XMASK;
}
public int LocalY (int y)
{
return y & CHUNK_YMASK;
}
public int LocalZ (int z)
{
return z & CHUNK_ZMASK;
}
public virtual Block GetBlock (int x, int y, int z)
{
_cache = GetChunk(x, y, z);
@ -56,52 +97,67 @@ namespace NBToolkit.Map
return null;
}
return new BlockRef(_cache, x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
return new BlockRef(_cache, x, y, z);
}
public virtual bool GetBlockID (int x, int y, int z, out int id)
public virtual BlockInfo GetBlockInfo (int x, int y, int z)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
id = 0;
return false;
return null;
}
id = _cache.GetBlockID(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
return true;
return _cache.GetBlockInfo(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
}
public virtual bool GetBlockData (int x, int y, int z, out int data) {
public virtual int GetBlockID (int x, int y, int z)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
data = 0;
return false;
if (_cache == null) {
return 0;
}
data = _cache.GetBlockData(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
return true;
return _cache.GetBlockID(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
}
public virtual bool GetBlockLight (int x, int y, int z, out int light) {
public virtual int GetBlockData (int x, int y, int z)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
light = 0;
return false;
if (_cache == null) {
return 0;
}
light = _cache.GetBlockLight(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
return true;
return _cache.GetBlockData(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
}
public virtual bool GetBlockSkyLight (int x, int y, int z, out int light) {
public virtual int GetBlockLight (int x, int y, int z)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
light = 0;
return false;
if (_cache == null) {
return 0;
}
light = _cache.GetBlockSkyLight(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
return true;
return _cache.GetBlockLight(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
}
public virtual int GetBlockSkyLight (int x, int y, int z)
{
_cache = GetChunk(x, y, z);
if (_cache == null) {
return 0;
}
return _cache.GetBlockSkyLight(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
}
public virtual void SetBlock (int x, int y, int z, Block block)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
return;
}
_cache.SetBlock(x & CHUNK_XMASK, y, z & CHUNK_ZMASK, block);
}
public virtual bool SetBlockID (int x, int y, int z, int id)
@ -124,11 +180,61 @@ namespace NBToolkit.Map
return _cache.SetBlockData(x & CHUNK_XMASK, y, z & CHUNK_ZMASK, data);
}
public ChunkRef GetChunk (int x, int y, int z)
public bool SetBlockLight (int x, int y, int z, int light)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
return false;
}
return _cache.SetBlockID(x & CHUNK_XMASK, y, z & CHUNK_ZMASK, light);
}
public bool SetBlockSkyLight (int x, int y, int z, int light)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
return false;
}
return _cache.SetBlockSkyLight(x & CHUNK_XMASK, y, z & CHUNK_ZMASK, light);
}
public virtual TileEntity GetTileEntity (int x, int y, int z)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
return null;
}
return _cache.GetTileEntity(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
}
public virtual bool SetTileEntity (int x, int y, int z, TileEntity te)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
return false;
}
return _cache.SetTileEntity(x & CHUNK_XMASK, y, z & CHUNK_ZMASK, te);
}
public virtual bool ClearTileEntity (int x, int y, int z)
{
_cache = GetChunk(x, y, z);
if (_cache == null || !Check(x, y, z)) {
return false;
}
return _cache.ClearTileEntity(x & CHUNK_XMASK, y, z & CHUNK_ZMASK);
}
protected ChunkRef GetChunk (int x, int y, int z)
{
x >>= CHUNK_XLOG;
z >>= CHUNK_ZLOG;
return _chunkMan.GetChunk(x, z);
return _chunkMan.GetChunkRef(x, z);
}
/// <summary>

View file

@ -5,6 +5,107 @@ using System.Text;
namespace NBToolkit.Map
{
public class BlockRef : IBlock
{
protected IBlockContainer _container;
protected int _x;
protected int _y;
protected int _z;
public int X
{
get { return _container.GlobalX(_x); }
}
public int Y
{
get { return _container.GlobalY(_y); }
}
public int Z
{
get { return _container.GlobalZ(_z); }
}
public int LocalX
{
get { return _container.LocalX(_x); }
}
public int LocalY
{
get { return _container.LocalZ(_z); }
}
public int LocalZ
{
get { return _z; }
}
public BlockInfo Info
{
get { return BlockInfo.BlockTable[_container.GetBlockID(_x, _y, _z)]; }
}
public int ID
{
get { return _container.GetBlockID(_x, _y, _z); }
set { _container.SetBlockID(_x, _y, _z, value); }
}
public int Data
{
get { return _container.GetBlockData(_x, _y, _z); }
set { _container.SetBlockData(_x, _y, _z, value); }
}
public int BlockLight
{
get { return _container.GetBlockLight(_x, _y, _z); }
set { _container.SetBlockLight(_x, _y, _z, value); }
}
public int SkyLight
{
get { return _container.GetBlockSkyLight(_x, _y, _z); }
set { _container.SetBlockSkyLight(_x, _y, _z, value); }
}
public BlockRef (IBlockContainer container, int x, int y, int z)
{
_container = container;
_x = x;
_y = y;
_z = z;
}
public void CopyFrom (IBlock block)
{
ID = block.ID;
Data = block.Data;
BlockLight = block.BlockLight;
SkyLight = block.SkyLight;
SetTileEntity(block.GetTileEntity().Copy());
}
public TileEntity GetTileEntity ()
{
return _container.GetTileEntity(_x, _y, _z);
}
public bool SetTileEntity (TileEntity te)
{
return _container.SetTileEntity(_x, _y, _z, te);
}
public bool ClearTileEntity ()
{
return _container.ClearTileEntity(_x, _y, _z);
}
}
/*public class BlockRef : IBlock
{
protected IChunk _chunk;
@ -101,5 +202,5 @@ namespace NBToolkit.Map
{
return _chunk.ClearTileEntity(_lx, _ly, _lz);
}
}
}*/
}

View file

@ -4,8 +4,41 @@ using System.IO;
namespace NBToolkit.Map
{
using NBT;
using Utility;
public interface IChunk
public interface IBlockContainer
{
int GlobalX (int x);
int GlobalY (int y);
int GlobalZ (int z);
int LocalX (int x);
int LocalY (int y);
int LocalZ (int z);
Block GetBlock (int lx, int ly, int lz);
BlockRef GetBlockRef (int lx, int ly, int lz);
BlockInfo GetBlockInfo (int lx, int ly, int lz);
int GetBlockID (int lx, int ly, int lz);
int GetBlockData (int lx, int ly, int lz);
int GetBlockLight (int lx, int ly, int lz);
int GetBlockSkyLight (int lx, int ly, int lz);
void SetBlock (int lx, int ly, int lz, Block block);
bool SetBlockID (int lx, int ly, int lz, int id);
bool SetBlockData (int lx, int ly, int lz, int data);
bool SetBlockLight (int lx, int ly, int lz, int light);
bool SetBlockSkyLight (int lx, int ly, int lz, int light);
TileEntity GetTileEntity (int lx, int ly, int lz);
bool SetTileEntity (int lx, int ly, int lz, TileEntity te);
bool ClearTileEntity (int lx, int ly, int lz);
}
public interface IChunk : IBlockContainer
{
int X { get; }
int Z { get; }
@ -14,31 +47,13 @@ namespace NBToolkit.Map
bool Save (Stream outStream);
Block GetBlock (int lx, int ly, int lz);
BlockRef GetBlockRef (int lx, int ly, int lz);
BlockInfo GetBlockInfo (int lx, int ly, int lz);
int GetBlockID (int lx, int ly, int lz);
int GetBlockData (int lx, int ly, int lz);
int GetBlockLight (int lx, int ly, int lz);
int GetBlockSkyLight (int lx, int ly, int lz);
bool SetBlockID (int lx, int ly, int lz, int id);
bool SetBlockData (int lx, int ly, int lz, int data);
bool SetBlockLight (int lx, int ly, int lz, int light);
bool SetBlockSkyLight (int lx, int ly, int lz, int light);
int CountBlockID (int id);
int CountBlockData (int id, int data);
int GetHeight (int lx, int lz);
TileEntity GetTileEntity (int lx, int ly, int lz);
bool SetTileEntity (int lx, int ly, int lz, TileEntity te);
bool ClearTileEntity (int lx, int ly, int lz);
}
public class Chunk : IChunk
public class Chunk : IChunk, ICopyable<Chunk>
{
private NBT_Tree _tree;
@ -134,6 +149,36 @@ namespace NBToolkit.Map
_tree.Root.Add("Level", level);
}
public int GlobalX (int x)
{
return _cx * BlockManager.CHUNK_XLEN + x;
}
public int GlobalY (int y)
{
return y;
}
public int GlobalZ (int z)
{
return _cz * BlockManager.CHUNK_ZLEN + z;
}
public int LocalX (int x)
{
return x;
}
public int LocalY (int y)
{
return y;
}
public int LocalZ (int z)
{
return z;
}
public bool Save (Stream outStream)
{
if (outStream == null || !outStream.CanWrite) {
@ -161,6 +206,19 @@ namespace NBToolkit.Map
return BlockInfo.BlockTable[GetBlockID(lx, ly, lz)];
}
public void SetBlock (int lx, int ly, int lz, Block block)
{
int index = lx << 11 | lz << 7 | ly;
SetBlockID(lx, ly, lz, block.ID);
SetBlockData(lx, ly, lz, block.Data);
_blockLight[index] = block.BlockLight;
_skyLight[index] = block.SkyLight;
SetTileEntity(lx, ly, lz, block.GetTileEntity().Copy());
}
public int GetBlockID (int lx, int ly, int lz)
{
return _blocks.Data[lx << 11 | lz << 7 | ly];
@ -197,17 +255,19 @@ namespace NBToolkit.Map
// Update height map
int tileHeight = GetHeight(lx, lz);
int newOpacity = BlockInfo.BlockTable[id].Opacity;
if (BlockInfo.BlockTable[id] != null) {
int tileHeight = GetHeight(lx, lz);
int newOpacity = BlockInfo.BlockTable[id].Opacity;
if (ly > tileHeight && newOpacity > BlockInfo.MIN_OPACITY) {
_heightMap[lz << 4 | lx] = (byte)ly;
}
else if (ly == tileHeight && newOpacity == BlockInfo.MIN_OPACITY) {
for (int i = ly - 1; i >= 0; i--) {
if (BlockInfo.BlockTable[GetBlockID(lx, i, lz)].Opacity > BlockInfo.MIN_OPACITY) {
_heightMap[lz << 4 | lx] = (byte)i;
break;
if (ly > tileHeight && newOpacity > BlockInfo.MIN_OPACITY) {
_heightMap[lz << 4 | lx] = (byte)ly;
}
else if (ly == tileHeight && newOpacity == BlockInfo.MIN_OPACITY) {
for (int i = ly - 1; i >= 0; i--) {
if (BlockInfo.BlockTable[GetBlockID(lx, i, lz)].Opacity > BlockInfo.MIN_OPACITY) {
_heightMap[lz << 4 | lx] = (byte)i;
break;
}
}
}
}
@ -225,6 +285,12 @@ namespace NBToolkit.Map
return false;
}
if (BlockManager.EnforceDataLimits && BlockInfo.BlockTable[_blocks[index]] != null) {
if (!BlockInfo.BlockTable[_blocks[index]].TestData(data)) {
return false;
}
}
_data[index] = data;
return true;
}
@ -360,5 +426,14 @@ namespace NBToolkit.Map
{
return _cz * BlockManager.CHUNK_ZLEN + lz;
}
#region ICopyable<Chunk> Members
public Chunk Copy ()
{
return new Chunk(_tree.Copy());
}
#endregion
}
}

View file

@ -90,7 +90,7 @@ namespace NBToolkit.Map
_region = _enum.Current;
}
if (MoveNextInRegion()) {
_chunk = _cm.GetChunkInRegion(_region, _x, _z);
_chunk = _cm.GetChunkRefInRegion(_region, _x, _z);
return true;
}
}

View file

@ -4,6 +4,26 @@ using System.Text;
namespace NBToolkit.Map
{
public interface IChunkManager
{
Chunk GetChunk (int cx, int cz);
ChunkRef GetChunkRef (int cx, int cz);
bool ChunkExists (int cx, int cz);
bool MarkChunkDirty (int cx, int cz);
bool MarkChunkClean (int cx, int cz);
int Save ();
bool Save (Chunk chunk);
ChunkRef CreateChunk (int cx, int cz);
bool DeleteChunk (int cx, int cz);
bool CopyChunk (int cx1, int cz1, int cx2, int cz2);
bool MoveChunk (int cx1, int cz1, int cx2, int cz2);
}
public class ChunkManager
{
public const int REGION_XLEN = 32;
@ -27,7 +47,20 @@ namespace NBToolkit.Map
_dirty = new Dictionary<ChunkKey, ChunkRef>();
}
public ChunkRef GetChunk (int cx, int cz)
public Chunk GetChunk (int cx, int cz)
{
int lcx = cx & REGION_XMASK;
int lcz = cz & REGION_ZMASK;
Region r = GetRegion(cx, cz);
if (r == null || !r.ChunkExists(lcx, lcz)) {
return null;
}
return new Chunk(r.GetChunkTree(lcx, lcz));
}
public ChunkRef GetChunkRef (int cx, int cz)
{
ChunkKey k = new ChunkKey(cx, cz);
@ -55,45 +88,49 @@ namespace NBToolkit.Map
}
}
public ChunkRef GetChunkInRegion (Region r, int lcx, int lcz)
public bool ChunkExists (int cx, int cz)
{
int cx = r.X * REGION_XLEN + lcx;
int cz = r.Z * REGION_ZLEN + lcz;
return GetChunk(cx, cz);
}
Region r = GetRegion(cx, cz);
if (r == null) {
return false;
}
public Region GetRegion (int cx, int cz)
{
cx >>= REGION_XLOG;
cz >>= REGION_ZLOG;
return _regionMan.GetRegion(cx, cz);
return r.ChunkExists(cx & REGION_XMASK, cz & REGION_ZMASK);
}
public bool MarkChunkDirty (int cx, int cz)
{
ChunkKey k = new ChunkKey(cx, cz);
if (!_dirty.ContainsKey(k)) {
_dirty.Add(k, GetChunk(cx, cz));
_dirty.Add(k, GetChunkRef(cx, cz));
return true;
}
return false;
}
public bool MarkChunkDirty (ChunkRef chunk)
public bool MarkChunkClean (int cx, int cz)
{
ChunkKey k = new ChunkKey(chunk.X, chunk.Z);
if (!_dirty.ContainsKey(k)) {
_dirty.Add(k, chunk);
ChunkKey k = new ChunkKey(cx, cz);
if (_dirty.ContainsKey(k)) {
_dirty.Remove(k);
return true;
}
return false;
}
public int SaveDirtyChunks ()
public int Save ()
{
int saved = 0;
foreach (ChunkRef c in _dirty.Values) {
if (c.Save()) {
int lcx = ChunkLocalX(c.X);
int lcz = ChunkLocalZ(c.Z);
Region r = GetRegion(c.X, c.Z);
if (r == null || !r.ChunkExists(lcx, lcz)) {
throw new MissingChunkException();
}
if (c.Save(r.GetChunkOutStream(lcx, lcz))) {
saved++;
}
}
@ -102,9 +139,14 @@ namespace NBToolkit.Map
return saved;
}
public RegionManager GetRegionManager ()
public bool Save (Chunk chunk)
{
return _regionMan;
Region r = GetRegion(chunk.X, chunk.Z);
if (r == null) {
return false;
}
return chunk.Save(r.GetChunkOutStream(chunk.X & REGION_XLEN, chunk.Z & REGION_ZLEN));
}
public bool DeleteChunk (int cx, int cz)
@ -128,6 +170,35 @@ namespace NBToolkit.Map
return true;
}
public RegionManager GetRegionManager ()
{
return _regionMan;
}
public ChunkRef GetChunkRefInRegion (Region r, int lcx, int lcz)
{
int cx = r.X * REGION_XLEN + lcx;
int cz = r.Z * REGION_ZLEN + lcz;
return GetChunkRef(cx, cz);
}
protected int ChunkLocalX (int cx)
{
return cx & REGION_XMASK;
}
protected int ChunkLocalZ (int cz)
{
return cz & REGION_ZMASK;
}
protected Region GetRegion (int cx, int cz)
{
cx >>= REGION_XLOG;
cz >>= REGION_ZLOG;
return _regionMan.GetRegion(cx, cz);
}
}
public class MissingChunkException : Exception

View file

@ -27,45 +27,63 @@ namespace NBToolkit.Map
get { return _cz; }
}
public int LocalX
{
get { return _cx & ChunkManager.REGION_XMASK; }
}
public int LocalZ
{
get { return _cz & ChunkManager.REGION_ZMASK; }
}
public ChunkRef (ChunkManager cm, int cx, int cz)
{
_chunkMan = cm;
_cx = cx;
_cz = cz;
Region r = cm.GetRegion(cx, cz);
if (r == null || !r.ChunkExists(LocalX, LocalZ)) {
if (!_chunkMan.ChunkExists(cx, cz)) {
throw new MissingChunkException();
}
}
public int GlobalX (int x)
{
return _cx * BlockManager.CHUNK_XLEN + x;
}
public int GlobalY (int y)
{
return y;
}
public int GlobalZ (int z)
{
return _cz * BlockManager.CHUNK_ZLEN + z;
}
public int LocalX (int x)
{
return x;
}
public int LocalY (int y)
{
return y;
}
public int LocalZ (int z)
{
return z;
}
private Chunk GetChunk ()
{
if (_chunk == null) {
_chunk = new Chunk(GetTree());
_chunk = _chunkMan.GetChunk(_cx, _cz);
}
return _chunk;
}
private NBT_Tree GetTree ()
/*private NBT_Tree GetTree ()
{
Region r = _chunkMan.GetRegion(_cx, _cz);
if (r == null || !r.ChunkExists(LocalX, LocalZ)) {
if (!_chunkMan.ChunkExists(_cx, _cz)) {
throw new MissingChunkException();
}
return r.GetChunkTree(LocalX, LocalZ);
}
}*/
private bool MarkDirty ()
{
@ -74,11 +92,11 @@ namespace NBToolkit.Map
}
_dirty = true;
_chunkMan.MarkChunkDirty(this);
_chunkMan.MarkChunkDirty(_cx, _cz);
return true;
}
public bool Save ()
/*public bool Save ()
{
if (_dirty) {
Region r = _chunkMan.GetRegion(_cx, _cz);
@ -93,26 +111,46 @@ namespace NBToolkit.Map
return false;
}
return true;
}
}*/
public ChunkRef GetNorthNeighbor ()
{
return _chunkMan.GetChunk(_cx - 1, _cz);
return _chunkMan.GetChunkRef(_cx - 1, _cz);
}
public ChunkRef GetSouthNeighbor ()
{
return _chunkMan.GetChunk(_cx + 1, _cz);
return _chunkMan.GetChunkRef(_cx + 1, _cz);
}
public ChunkRef GetEastNeighbor ()
{
return _chunkMan.GetChunk(_cx, _cz - 1);
return _chunkMan.GetChunkRef(_cx, _cz - 1);
}
public ChunkRef GetWestNeighbor ()
{
return _chunkMan.GetChunk(_cx, _cz + 1);
return _chunkMan.GetChunkRef(_cx, _cz + 1);
}
public Chunk GetChunkCopy ()
{
return GetChunk().Copy();
}
public Chunk GetChunkRef ()
{
Chunk chunk = GetChunk();
_chunk = null;
return chunk;
}
public void SetChunkRef (Chunk chunk)
{
_chunk = chunk;
_chunk.SetLocation(_cx, _cz);
MarkDirty();
}
#region IChunk Members
@ -156,6 +194,11 @@ namespace NBToolkit.Map
return GetChunk().GetBlockInfo(lx, ly, lz);
}
public void SetBlock (int lx, int ly, int lz, Block block)
{
GetChunk().SetBlock(lx, ly, lz, block);
}
public int GetBlockID (int lx, int ly, int lz)
{
return GetChunk().GetBlockID(lx, ly, lz);

View file

@ -8,7 +8,7 @@ namespace NBToolkit.Map.NBT
{
using Map.Utility;
public class NBT_Tree
public class NBT_Tree : ICopyable<NBT_Tree>
{
private Stream _stream = null;
private NBT_Compound _root = null;
@ -459,6 +459,18 @@ namespace NBToolkit.Map.NBT
WriteValue(val);
}
}
#region ICopyable<NBT_Tree> Members
public NBT_Tree Copy ()
{
NBT_Tree tree = new NBT_Tree();
tree._root = _root.Copy() as NBT_Compound;
return tree;
}
#endregion
}
public class NBTException : Exception

View file

@ -8,6 +8,36 @@ namespace NBToolkit.Map
{
using NBT;
public interface IChunkContainer
{
int GlobalX (int cx);
int GlobalZ (int cz);
int LocalX (int cx);
int LocalZ (int cz);
Chunk GetChunk (int cx, int cz);
ChunkRef GetChunkRef (int cx, int cz);
bool ChunkExists (int cx, int cz);
bool DeleteChunk (int cx, int cz);
bool Save ();
bool SaveChunk (Chunk chunk);
bool MarkChunkDirty (int cx, int cz);
bool MarkChunkClean (int cx, int cz);
}
public interface IRegion : IChunkContainer
{
int X { get; }
int Z { get; }
int ChunkCount ();
}
public class Region : IDisposable
{
protected int _rx;
@ -20,6 +50,16 @@ namespace NBToolkit.Map
protected WeakReference _regionFile;
public int X
{
get { return _rx; }
}
public int Z
{
get { return _rz; }
}
public Region (RegionManager rm, int rx, int rz)
{
_regionMan = rm;
@ -44,22 +84,6 @@ namespace NBToolkit.Map
}
}
public int X
{
get
{
return _rx;
}
}
public int Z
{
get
{
return _rz;
}
}
~Region ()
{
Dispose(false);
@ -88,6 +112,20 @@ namespace NBToolkit.Map
_disposed = true;
}
public Chunk GetChunk (int lcx, int lcz)
{
if (!ChunkExists(lcx, lcz)) {
return null;
}
return new Chunk(GetChunkTree(lcx, lcz));
}
//public ChunkRef GetChunkRef (int lcx, int lcz)
//{
//}
public string GetFileName ()
{
return "r." + _rx + "." + _rz + ".mcr";

View file

@ -16,6 +16,15 @@ namespace NBToolkit.Map
get { return _tree; }
}
public TileEntity (string id)
{
_tree = new NBT_Compound();
_tree["id"] = new NBT_String(id);
_tree["x"] = new NBT_Int();
_tree["y"] = new NBT_Int();
_tree["z"] = new NBT_Int();
}
public TileEntity (NBT_Compound tree)
{
_tree = tree;
@ -77,7 +86,7 @@ namespace NBToolkit.Map
new NBTStringNode("id", "Furnace"),
new NBTScalerNode("BurnTime", NBT_Type.TAG_SHORT),
new NBTScalerNode("CookTime", NBT_Type.TAG_SHORT),
new NBTListNode("Items", NBT_Type.TAG_COMPOUND),
new NBTListNode("Items", NBT_Type.TAG_COMPOUND, InventorySchema),
});
public static readonly NBTCompoundNode SignSchema = BaseSchema.MergeInto(new NBTCompoundNode("")

View file

@ -3,9 +3,9 @@ using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace NBToolkit
namespace NBToolkit.Map.Utility
{
public class NibbleArray
public class NibbleArray : ICopyable<NibbleArray>
{
protected readonly byte[] _data = null;
@ -46,5 +46,17 @@ namespace NBToolkit
return _data.Length << 1;
}
}
#region ICopyable<NibbleArray> Members
public NibbleArray Copy ()
{
byte[] data = new byte[_data.Length];
_data.CopyTo(data, 0);
return new NibbleArray(data);
}
#endregion
}
}