Update: Simplified the data structure modelling a single block in the world. It is now basically this:
struct Block {
uint16 type;
uint16 data;
};
block.type is split into 6 bits for the mod id and the last 10 bits for the sub-type of the block. This means that each mod can register up to 1024 block types, so lots of room for future expansion.

block.data has 16 bits available for the block states, this includes whether the block is flipped (in the case of slopes), or which variant of the block is being used (e.g., the tree block has 6 variations), and the other bits will be used for other things.
Each block.type has a corresponding BlockInfo which stores information relevant to that type..
struct BlockInfo {
string name, doc;
BlockSprite sprite;
DamageType damageType;
...
};
I was originally going to store block damage and lighting in the Block, but now I think I'll handle the damage externally, doing a minecraft-like temporary damage model, and, as for lighting, I'm not sure it'll make it into the game at this stage.
Also, I'm spending way too much time making things in-game instead of coding.. O_O
