Files

514 lines
17 KiB
C++

#pragma once
#include <cstdint>
namespace vf {
enum class Block : uint8_t {
Air = 0,
Grass = 1,
Dirt = 2,
Stone = 3,
Sand = 4,
Wood = 5,
Leaves = 6,
Water = 7,
Snow = 8,
CoalOre = 9,
IronOre = 10,
GoldOre = 11,
Gravel = 12,
Glowstone = 13,
// --- extended palette (wave 1, additive; values above are frozen) ---
Cobblestone = 14,
Planks = 15,
Sandstone = 16,
Ice = 17,
Bedrock = 18,
Obsidian = 19,
Lava = 20,
DiamondOre = 21,
RedstoneOre = 22,
EmeraldOre = 23,
LapisOre = 24,
CraftingTable = 25,
Furnace = 26,
FurnaceLit = 27,
Chest = 28,
Torch = 29,
RedstoneWire = 30,
RedstoneTorch = 31,
RedstoneLamp = 32,
RedstoneLampLit = 33,
Lever = 34,
Button = 35,
RedstoneBlock = 36,
Repeater = 37,
Comparator = 38,
Piston = 39,
PistonSticky = 40,
PistonHead = 41,
Tnt = 42,
Ladder = 43,
// --- extended palette (wave 2, additive; values above are frozen) ---
// Automation & logistics (agent A).
Rail = 44,
PoweredRail = 45,
DetectorRail = 46,
ActivatorRail = 47,
Hopper = 48,
Dropper = 49,
Dispenser = 50,
Observer = 51,
TargetBlock = 52,
SlimeBlock = 53,
NoteBlock = 54,
// Environment, farming & climate (agent B).
Farmland = 55,
Wheat = 56,
Carrot = 57,
Potato = 58,
Pumpkin = 59,
Melon = 60,
PumpkinStem = 61,
MelonStem = 62,
SugarCane = 63,
Cactus = 64,
Sapling = 65,
Vine = 66,
SnowLayer = 67,
PackedIce = 68,
// --- extended palette (wave 5, additive; values above are frozen) ---
// Combat, brewing, enchanting.
BrewingStand = 69,
EnchantingTable = 70,
Cauldron = 71,
AnvilBlock = 72,
Bookshelf = 73,
Cobweb = 74,
// --- extended palette (wave 6, additive) ---
// Nether and End dimensions.
Netherrack = 75,
SoulSand = 76,
SoulSoil = 77,
NetherQuartzOre = 78,
NetherBrick = 79,
NetherPortal = 80,
Magma = 81,
Basalt = 82,
Blackstone = 83,
EndStone = 84,
EndPortal = 85,
EndPortalFrame = 86,
Purpur = 87,
ChorusPlant = 88,
ChorusFlower = 89,
// Village and construction blocks.
Glass = 90,
Bricks = 91,
StoneBricks = 92,
MossyCobblestone = 93,
Door = 94,
Slab = 95,
Stairs = 96,
Fence = 97,
Bed = 98,
Bell = 99,
Lantern = 100,
Composter = 101,
Barrel = 102,
SmithingTable = 103,
Loom = 104,
CartographyTable = 105,
Grindstone = 106,
Stonecutter = 107,
Lectern = 108,
HayBale = 109,
// --- extended palette (waves 7-8, additive) ---
// Geology, loot and decoration.
Clay = 110,
Terracotta = 111,
Wool = 112,
Mycelium = 113,
Andesite = 114,
Diorite = 115,
Granite = 116,
Deepslate = 117,
CopperOre = 118,
Tuff = 119,
Dripstone = 120,
AmethystBlock = 121,
Sculk = 122,
CryingObsidian = 123,
Prismarine = 124,
SeaLantern = 125,
Kelp = 126,
Coral = 127,
Mud = 128,
Moss = 129,
Count
};
enum class Face : uint8_t {
PosX = 0,
NegX = 1,
PosY = 2,
NegY = 3,
PosZ = 4,
NegZ = 5,
};
inline bool isAir(Block b) { return b == Block::Air; }
// Non-solid blocks are walked through: fluids and thin redstone/utility parts.
inline bool isSolid(Block b) {
switch (b) {
case Block::Air:
case Block::Water:
case Block::Lava:
case Block::Torch:
case Block::RedstoneTorch:
case Block::RedstoneWire:
case Block::Lever:
case Block::Button:
case Block::Repeater:
case Block::Comparator:
case Block::Ladder:
case Block::Rail:
case Block::PoweredRail:
case Block::DetectorRail:
case Block::ActivatorRail:
case Block::Wheat:
case Block::Carrot:
case Block::Potato:
case Block::PumpkinStem:
case Block::MelonStem:
case Block::SugarCane:
case Block::Sapling:
case Block::Vine:
case Block::SnowLayer:
case Block::BrewingStand:
case Block::Cobweb:
case Block::NetherPortal:
case Block::EndPortal:
case Block::Door:
case Block::Lantern:
case Block::Bell:
case Block::Kelp:
case Block::ChorusFlower:
return false;
default:
return true;
}
}
// Opaque blocks fully hide the neighbouring face. Leaves, fluids, ice and the
// thin redstone/utility blocks do not.
inline bool isOpaque(Block b) {
switch (b) {
case Block::Air:
case Block::Leaves:
case Block::Water:
case Block::Ice:
case Block::Torch:
case Block::RedstoneWire:
case Block::RedstoneTorch:
case Block::Lever:
case Block::Button:
case Block::Repeater:
case Block::Comparator:
case Block::Ladder:
case Block::Rail:
case Block::PoweredRail:
case Block::DetectorRail:
case Block::ActivatorRail:
case Block::Hopper:
case Block::Cactus:
case Block::Wheat:
case Block::Carrot:
case Block::Potato:
case Block::PumpkinStem:
case Block::MelonStem:
case Block::SugarCane:
case Block::Sapling:
case Block::Vine:
case Block::SnowLayer:
case Block::Glass:
case Block::NetherPortal:
case Block::EndPortal:
case Block::Cobweb:
case Block::BrewingStand:
case Block::EnchantingTable:
case Block::Cauldron:
case Block::AnvilBlock:
case Block::Door:
case Block::Slab:
case Block::Stairs:
case Block::Fence:
case Block::Bed:
case Block::Bell:
case Block::Lantern:
case Block::Kelp:
case Block::ChorusPlant:
case Block::ChorusFlower:
case Block::Composter:
case Block::Grindstone:
case Block::Lectern:
case Block::Stonecutter:
return false;
default:
return true;
}
}
// Whether a face of `self` should be emitted given the neighbour `other`.
// A face is visible when the neighbour does not opaquely cover it, and the
// two blocks are not the same translucent type (so water/leaves/ice do not
// draw internal seams against their own kind).
inline bool faceVisible(Block self, Block other) {
if (isAir(self)) return false;
if (isOpaque(other)) return false;
if (self == other) return false;
return true;
}
// Texture-array layer for a given block face. Sided blocks vary by face.
inline int faceTile(Block block, Face face) {
switch (block) {
case Block::Grass:
if (face == Face::PosY) return 0; // grass top
if (face == Face::NegY) return 2; // dirt bottom
return 1; // grass side
case Block::Dirt: return 2;
case Block::Stone: return 3;
case Block::Sand: return 4;
case Block::Wood:
if (face == Face::PosY || face == Face::NegY) return 6; // rings
return 5; // bark
case Block::Leaves: return 7;
case Block::Water: return 8;
case Block::Snow: return 9;
case Block::CoalOre: return 10;
case Block::IronOre: return 11;
case Block::GoldOre: return 12;
case Block::Gravel: return 13;
case Block::Glowstone: return 14;
case Block::Cobblestone: return 15;
case Block::Planks: return 16;
case Block::Sandstone:
if (face == Face::PosY || face == Face::NegY) return 17; // top/bottom
return 18; // side
case Block::Ice: return 19;
case Block::Bedrock: return 20;
case Block::Obsidian: return 21;
case Block::Lava: return 22;
case Block::DiamondOre: return 23;
case Block::RedstoneOre: return 24;
case Block::EmeraldOre: return 25;
case Block::LapisOre: return 26;
case Block::CraftingTable:
if (face == Face::PosY) return 27; // grid top
if (face == Face::NegY) return 16; // planks bottom
return 28; // tools side
case Block::Furnace:
if (face == Face::PosZ) return 29; // cold front
if (face == Face::PosY || face == Face::NegY) return 30;
return 30; // side
case Block::FurnaceLit:
if (face == Face::PosZ) return 31; // burning front
return 30;
case Block::Chest: return 32;
case Block::Torch: return 33;
case Block::RedstoneWire: return 34;
case Block::RedstoneTorch: return 35;
case Block::RedstoneLamp: return 36;
case Block::RedstoneLampLit: return 37;
case Block::Lever: return 38;
case Block::Button: return 39;
case Block::RedstoneBlock: return 40;
case Block::Repeater: return 41;
case Block::Comparator: return 42;
case Block::Piston:
if (face == Face::PosZ) return 43; // face plate
if (face == Face::NegZ) return 45; // back
return 44; // side
case Block::PistonSticky:
if (face == Face::PosZ) return 46; // sticky face
if (face == Face::NegZ) return 45;
return 44;
case Block::PistonHead: return 47;
case Block::Tnt:
if (face == Face::PosY || face == Face::NegY) return 48; // caps
return 49; // fuse band
case Block::Ladder: return 50;
case Block::Rail: return 51;
case Block::PoweredRail: return 52;
case Block::DetectorRail: return 53;
case Block::ActivatorRail: return 54;
case Block::Hopper: return 55;
case Block::Dropper: return 56;
case Block::Dispenser: return 57;
case Block::Observer: return 58;
case Block::TargetBlock: return 59;
case Block::SlimeBlock: return 60;
case Block::NoteBlock: return 61;
case Block::Farmland:
if (face == Face::PosY) return 62; // tilled top
return 2; // dirt sides/bottom
case Block::Wheat: return 63;
case Block::Carrot: return 64;
case Block::Potato: return 65;
case Block::Pumpkin:
if (face == Face::PosY || face == Face::NegY) return 66;
return 67;
case Block::Melon:
if (face == Face::PosY || face == Face::NegY) return 68;
return 69;
case Block::PumpkinStem: return 70;
case Block::MelonStem: return 71;
case Block::SugarCane: return 72;
case Block::Cactus:
if (face == Face::PosY) return 73;
if (face == Face::NegY) return 74;
return 75;
case Block::Sapling: return 76;
case Block::Vine: return 77;
case Block::SnowLayer: return 78;
case Block::PackedIce: return 79;
case Block::BrewingStand: return 80;
case Block::EnchantingTable:
if (face == Face::PosY) return 81; // arcane book cover
if (face == Face::NegY) return 21; // obsidian base
return 82; // side
case Block::Cauldron:
if (face == Face::PosY) return 83; // rim with water
return 84; // iron side
case Block::AnvilBlock:
if (face == Face::PosY) return 85; // worn face
return 86; // side
case Block::Bookshelf:
if (face == Face::PosY || face == Face::NegY) return 16; // planks
return 87; // spines
case Block::Cobweb: return 88;
case Block::Netherrack: return 89;
case Block::SoulSand: return 90;
case Block::SoulSoil: return 91;
case Block::NetherQuartzOre: return 92;
case Block::NetherBrick: return 93;
case Block::NetherPortal: return 94;
case Block::Magma: return 95;
case Block::Basalt:
if (face == Face::PosY || face == Face::NegY) return 96; // cracked cap
return 97; // column side
case Block::Blackstone: return 98;
case Block::EndStone: return 99;
case Block::EndPortal: return 100;
case Block::EndPortalFrame:
if (face == Face::PosY) return 101; // eye socket
return 102; // side
case Block::Purpur: return 103;
case Block::ChorusPlant: return 104;
case Block::ChorusFlower: return 105;
case Block::Glass: return 106;
case Block::Bricks: return 107;
case Block::StoneBricks: return 108;
case Block::MossyCobblestone: return 109;
case Block::Door: return 110;
case Block::Slab:
if (face == Face::PosY || face == Face::NegY) return 111; // cut face
return 112; // profile
case Block::Stairs: return 112;
case Block::Fence: return 113;
case Block::Bed:
if (face == Face::PosY) return 114; // quilt
return 115; // frame
case Block::Bell: return 116;
case Block::Lantern: return 117;
case Block::Composter:
if (face == Face::PosY) return 118; // open compost
return 119; // slats
case Block::Barrel:
if (face == Face::PosY || face == Face::NegY) return 120; // lid
return 121; // staves
case Block::SmithingTable:
if (face == Face::PosY) return 122;
return 123;
case Block::Loom:
if (face == Face::PosY) return 124;
return 125;
case Block::CartographyTable:
if (face == Face::PosY) return 126;
return 127;
case Block::Grindstone: return 128;
case Block::Stonecutter:
if (face == Face::PosY) return 129;
return 130;
case Block::Lectern:
if (face == Face::PosY) return 131;
return 132;
case Block::HayBale:
if (face == Face::PosY || face == Face::NegY) return 133; // cut ends
return 134; // bound side
case Block::Clay: return 135;
case Block::Terracotta: return 136;
case Block::Wool: return 137;
case Block::Mycelium:
if (face == Face::PosY) return 138;
if (face == Face::NegY) return 2; // dirt bottom
return 139;
case Block::Andesite: return 140;
case Block::Diorite: return 141;
case Block::Granite: return 142;
case Block::Deepslate:
if (face == Face::PosY || face == Face::NegY) return 143; // cut face
return 144; // striated side
case Block::CopperOre: return 145;
case Block::Tuff: return 146;
case Block::Dripstone: return 147;
case Block::AmethystBlock: return 148;
case Block::Sculk: return 149;
case Block::CryingObsidian: return 150;
case Block::Prismarine: return 151;
case Block::SeaLantern: return 152;
case Block::Kelp: return 153;
case Block::Coral: return 154;
case Block::Mud: return 155;
case Block::Moss: return 156;
default: return 3;
}
}
constexpr int tileCount = 157;
// Block light emitted by a block itself, 0..15.
inline int blockLightEmission(Block b) {
switch (b) {
case Block::Glowstone: return 15;
case Block::Lava: return 15;
case Block::RedstoneLampLit: return 15;
case Block::Torch: return 14;
case Block::FurnaceLit: return 13;
case Block::RedstoneTorch: return 7;
case Block::RedstoneOre: return 0; // lit only on touch, handled by gameplay
case Block::EndPortal: return 15;
case Block::SeaLantern: return 15;
case Block::Lantern: return 15;
case Block::NetherPortal: return 11;
case Block::CryingObsidian: return 10;
case Block::EnchantingTable: return 7;
case Block::Magma: return 3;
default: return 0;
}
}
// A block that ambient-occludes its neighbours and blocks light propagation.
inline bool occludesLight(Block b) { return isOpaque(b); }
// Meshed in the transparent pass (depth write off, back-to-front): fluids + ice.
inline bool isTransparent(Block b) {
return b == Block::Water || b == Block::Ice || b == Block::Glass ||
b == Block::NetherPortal || b == Block::EndPortal;
}
} // namespace vf