506 lines
16 KiB
C++
506 lines
16 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
|
|
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;
|
|
}
|
|
|
|
} // namespace vf
|