using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MinecraftClient.Mapping.BlockPalettes;
namespace MinecraftClient.Mapping
{
///
/// Represents a Minecraft Block
///
public struct Block
{
///
/// Get or set global block ID to Material mapping
/// The global Palette is a concept introduced with Minecraft 1.13
///
public static BlockPaletteMapping Palette { get; set; }
///
/// Storage for block ID and metadata, as ushort for compatibility, performance and lower memory footprint
/// For Minecraft 1.12 and lower, first 12 bits contain block ID (0-4095), last 4 bits contain metadata (0-15)
/// For Minecraft 1.13 and greater, all 16 bits are used to store block state ID (0-65535)
///
private ushort blockIdAndMeta;
///
/// Id of the block
///
public int BlockId
{
get
{
if (Palette.IdHasMetadata)
{
return blockIdAndMeta >> 4;
}
return blockIdAndMeta;
}
set
{
if (Palette.IdHasMetadata)
{
if (value > (ushort.MaxValue >> 4) || value < 0)
throw new ArgumentOutOfRangeException("value", "Invalid block ID. Accepted range: 0-4095");
blockIdAndMeta = (ushort)(value << 4 | BlockMeta);
}
else
{
if (value > ushort.MaxValue || value < 0)
throw new ArgumentOutOfRangeException("value", "Invalid block ID. Accepted range: 0-65535");
blockIdAndMeta = (ushort)value;
}
}
}
///
/// Metadata of the block.
/// This field has no effect starting with Minecraft 1.13.
///
public byte BlockMeta
{
get
{
if (Palette.IdHasMetadata)
{
return (byte)(blockIdAndMeta & 0x0F);
}
return 0;
}
set
{
if (Palette.IdHasMetadata)
{
blockIdAndMeta = (ushort)((blockIdAndMeta & ~0x0F) | (value & 0x0F));
}
}
}
///
/// Material of the block
///
public Material Type
{
get
{
return Palette.FromId(BlockId);
}
}
///
/// Get a block of the specified type and metadata
///
/// Block type
/// Block metadata
public Block(short type, byte metadata)
{
if (!Palette.IdHasMetadata)
throw new InvalidOperationException("Current global Palette does not support block Metadata");
this.blockIdAndMeta = 0;
this.BlockId = type;
this.BlockMeta = metadata;
}
///
/// Get a block of the specified type and metadata OR block state
///
/// Type and metadata packed in the same value OR block state
public Block(ushort typeAndMeta)
{
this.blockIdAndMeta = typeAndMeta;
}
///
/// String representation of the block
///
public override string ToString()
{
return BlockId.ToString() + (BlockMeta != 0 ? ":" + BlockMeta.ToString() : "");
}
}
}