alex/beta-minecraft-rust
Minecraft Beta 1.7.3 Rewrite
BRANCH main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
root crates common src stats.rs
use crate::item::{Item, ItemStack};
use crate::world::Block;
pub const ACHIEVEMENT: i32 = 5242880;
pub const MINE: i32 = 16777216;
pub const CRAFT: i32 = 16842752;
pub const USE: i32 = 16908288;
pub const BREAK: i32 = 16973824;
pub struct Achievement {
pub name: &'static str,
pub position: [i32; 2],
pub icon: Item,
pub parent: Option<usize>,
pub special: bool,
}
macro_rules! achievements {
($($name:literal, $x:literal, $y:literal, $icon:expr, $parent:expr, $special:literal;)*) => {
[$(Achievement {
name: $name,
position: [$x, $y],
icon: $icon,
parent: $parent,
special: $special,
}),*]
};
}
pub const ACHIEVEMENTS: [Achievement; 16] = achievements![
"openInventory", 0, 0, Item::BOOK, None, false;
"mineWood", 2, 1, Item::from_block(Block::LOG), Some(0), false;
"buildWorkBench", 4, -1, Item::from_block(Block::CRAFTING_TABLE), Some(1), false;
"buildPickaxe", 4, 2, Item::WOODEN_PICKAXE, Some(2), false;
"buildFurnace", 3, 4, Item::from_block(Block::LIT_FURNACE), Some(3), false;
"acquireIron", 1, 4, Item::IRON_INGOT, Some(4), false;
"buildHoe", 2, -3, Item::WOODEN_HOE, Some(2), false;
"makeBread", -1, -3, Item::BREAD, Some(6), false;
"bakeCake", 0, -5, Item::CAKE, Some(6), false;
"buildBetterPickaxe", 6, 2, Item::STONE_PICKAXE, Some(3), false;
"cookFish", 2, 6, Item::COOKED_FISH, Some(4), false;
"onARail", 2, 3, Item::from_block(Block::RAIL), Some(5), true;
"buildSword", 6, -1, Item::WOODEN_SWORD, Some(2), false;
"killEnemy", 8, -1, Item::BONE, Some(12), false;
"killCow", 7, -3, Item::LEATHER, Some(12), false;
"flyPig", 8, -4, Item::SADDLE, Some(14), true;
];
pub const GENERAL: [(i32, &str); 23] = [
(1000, "startGame"),
(1001, "createWorld"),
(1002, "loadWorld"),
(1003, "joinMultiplayer"),
(1004, "leaveGame"),
(1100, "playOneMinute"),
(2000, "walkOneCm"),
(2001, "swimOneCm"),
(2002, "fallOneCm"),
(2003, "climbOneCm"),
(2004, "flyOneCm"),
(2005, "diveOneCm"),
(2006, "minecartOneCm"),
(2007, "boatOneCm"),
(2008, "pigOneCm"),
(2010, "jump"),
(2011, "drop"),
(2020, "damageDealt"),
(2021, "damageTaken"),
(2022, "deaths"),
(2023, "mobKills"),
(2024, "playerKills"),
(2025, "fishCaught"),
];
pub fn independent(id: i32) -> bool {
matches!(id,1000..=1004|1100|2000..=2008|2010|2011) || id == ACHIEVEMENT
}
pub fn block_id(block: Block) -> i32 {
i32::from(
match block {
Block::WATER => Block::FLOWING_WATER,
Block::JACK_O_LANTERN => Block::PUMPKIN,
Block::LIT_FURNACE => Block::FURNACE,
Block::LIT_REDSTONE_ORE => Block::REDSTONE_ORE,
Block::POWERED_REPEATER => Block::REPEATER,
Block::REDSTONE_TORCH => Block::UNLIT_REDSTONE_TORCH,
Block::RED_MUSHROOM => Block::BROWN_MUSHROOM,
Block::DOUBLE_SLAB => Block::SLAB,
Block::GRASS | Block::FARMLAND => Block::DIRT,
other => other,
}
.0,
)
}
pub fn item_id(item: Item) -> i32 {
item.block().map_or(i32::from(item.0), block_id)
}
pub fn crafted_achievement(stack: ItemStack) -> Option<usize> {
match stack.item {
Item::WOODEN_PICKAXE => Some(3),
Item::WOODEN_HOE => Some(6),
Item::BREAD => Some(7),
Item::CAKE => Some(8),
Item::STONE_PICKAXE | Item::IRON_PICKAXE | Item::DIAMOND_PICKAXE | Item::GOLDEN_PICKAXE => {
Some(9)
}
Item::WOODEN_SWORD => Some(12),
item if item == Item::from_block(Block::CRAFTING_TABLE) => Some(2),
item if item == Item::from_block(Block::FURNACE) => Some(4),
_ => None,
}
}
/// Languages whose locale separates decimals by a comma.
const COMMA_LANGUAGES: [&str; 31] = [
"bg", "ca", "cs", "da", "de", "el", "es", "et", "fi", "fr", "hr", "hu", "id", "it", "lt", "lv",
"nb", "nl", "nn", "no", "pl", "pt", "ro", "ru", "sk", "sl", "sr", "sv", "tr", "uk", "vi",
];
/// `DecimalFormat` symbols of the platform locale: whether it separates decimals by a comma.
fn decimal_comma() -> bool {
static COMMA: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
*COMMA.get_or_init(|| {
let locale = ["LC_ALL", "LC_NUMERIC", "LANG"]
.into_iter()
.filter_map(|key| std::env::var(key).ok())
.find(|value| !value.is_empty())
.unwrap_or_default();
let language = locale
.split(['_', '.', '@', '-'])
.next()
.unwrap_or_default();
COMMA_LANGUAGES.contains(&language)
})
}
/// `new DecimalFormat("########0.00")` in the platform locale.
fn decimal(value: f64) -> String {
let text = format!("{value:.2}");
if decimal_comma() {
text.replace('.', ",")
} else {
text
}
}
pub fn format(id: i32, value: i32) -> String {
if id == 1100 {
let seconds = f64::from(value) / 20.0;
for (divisor, unit) in [
(31536000.0, "y"),
(86400.0, "d"),
(3600.0, "h"),
(60.0, "m"),
] {
if seconds / divisor > 0.5 {
return format!("{} {unit}", decimal(seconds / divisor));
}
}
return format!("{seconds:?} s");
}
if (2000..=2008).contains(&id) {
if value > 50000 {
return format!("{} km", decimal(f64::from(value) / 100000.0));
}
if value > 50 {
return format!("{} m", decimal(f64::from(value) / 100.0));
}
return format!("{value} cm");
}
let digits = value.to_string();
let mut grouped = String::new();
for (index, ch) in digits.chars().enumerate() {
if index > 0 && ch.is_ascii_digit() && (digits.len() - index).is_multiple_of(3) {
grouped.push(',');
}
grouped.push(ch);
}
grouped
}