From e0f48fad20fb784b27a59cbfc0753525a3403042 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Sun, 23 Aug 2026 12:31:48 +0200 Subject: [PATCH] feat(core): add block type enum and per-block properties --- core/include/vf/Block.h | 307 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 core/include/vf/Block.h diff --git a/core/include/vf/Block.h b/core/include/vf/Block.h new file mode 100644 index 0000000..408c812 --- /dev/null +++ b/core/include/vf/Block.h @@ -0,0 +1,307 @@ +#pragma once + +#include + +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, + 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: + 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: + 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; + default: return 3; + } +} + +constexpr int tileCount = 80; + +// 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