# mcdata-rs
[](https://crates.io/crates/mcdata-rs)
[](https://docs.rs/mcdata-rs)
[](https://opensource.org/licenses/MIT)
A Rust library providing easy access to Minecraft data sourced from the comprehensive [PrismarineJS/minecraft-data](https://github.com/PrismarineJS/minecraft-data) repository. It handles automatic downloading, caching, and indexing of data for various Minecraft versions.
## Features
* Access to indexed Minecraft data (Blocks, Items, Entities, Biomes, Effects, Foods, etc.) by ID and name.
* Automatic download and caching of `minecraft-data` files on first use.
* Helper functions for version comparison (`is_newer_or_equal_to`, `is_older_than`).
* Feature checking based on `features.json` (`support_feature`).
* Lazy loading and caching of data per version for efficient memory usage.
## Installation
Add `mcdata-rs` to your `Cargo.toml`:
```toml
[dependencies]
mcdata-rs = "0.1.0" # Replace with the actual latest version from crates.io
```
## Data Cache
The library automatically downloads the necessary `minecraft-data` files on the first run for a given version (or if the cache is missing/corrupted). This data is stored in your system's standard cache directory:
* **Linux:** `~/.cache/mcdata-rs/minecraft-data`
* **macOS:** `~/Library/Caches/mcdata-rs/minecraft-data`
* **Windows:** `%LOCALAPPDATA%\mcdata-rs\minecraft-data`
The initial download might take a moment depending on your network connection. Subsequent runs using the same version will load data instantly from the cache.
*(Optional)*: For debugging download or cache issues, enable logging by setting the `RUST_LOG` environment variable (e.g., `RUST_LOG=mcdata_rs=debug cargo run`).
## API and Usage Examples
The main entry point is the `mc_data(&str)` function, which takes a version string and returns a `Result<Arc<IndexedData>, McDataError>`. The `IndexedData` struct contains all the loaded and indexed data for that version, wrapped in `Arc` for efficient sharing.
```rust
use mcdata_rs::*; // Import necessary items
use std::sync::Arc;
fn main() -> Result<(), McDataError> {
// --- Get Data for a Specific Version ---
// Accepts version strings like "1.18.2", "pc_1.16.5", "1.19" (latest release), etc.
// This might download data on the first run for this version.
let data_1_18_2: Arc<IndexedData> = mc_data("1.18.2")?;
println!("Loaded data for Minecraft PC {}", data_1_18_2.version.minecraft_version);
// --- Accessing Indexed Data ---
// By Name (most common for blocks, items, entities, etc.)
if let Some(stone) = data_1_18_2.blocks_by_name.get("stone") {
println!("Stone Info:");
println!(" ID: {}", stone.id);
println!(" Display Name: {}", stone.display_name);
println!(" Hardness: {:?}", stone.hardness);
println!(" Diggable: {}", stone.diggable);
}
if let Some(stick) = data_1_18_2.items_by_name.get("stick") {
println!("Stick stack size: {}", stick.stack_size);
}
if let Some(zombie) = data_1_18_2.entities_by_name.get("zombie") {
println!("Zombie category: {:?}", zombie.category);
}
// By ID
if let Some(block_id_1) = data_1_18_2.blocks_by_id.get(&1) {
// Note: Block ID 1 is typically stone in many versions, but not guaranteed.
println!("Block with ID 1: {}", block_id_1.name);
}
// By State ID (for blocks >= 1.13)
let stone_block = data_1_18_2.blocks_by_name.get("stone").unwrap(); // Assume stone exists
if let Some(block_from_state) = data_1_18_2.blocks_by_state_id.get(&stone_block.default_state) {
println!("Block for default state {}: {}", stone_block.default_state, block_from_state.name);
}
// Accessing Arrays (less common, but available)
println!("First loaded block: {}", data_1_18_2.blocks_array[0].name);
println!("Total loaded items: {}", data_1_18_2.items_array.len());
// --- Using Helper Functions ---
// Version Comparison
let data_1_16_5 = mc_data("1.16.5")?;
assert!(data_1_18_2.is_newer_or_equal_to("1.16.5")?);
assert!(data_1_16_5.is_older_than("1.18.2")?);
assert!(!data_1_18_2.is_older_than("1.18.2")?);
// Feature Checking (based on features.json)
// Check if dimensions were represented as an Integer in 1.15.2
let data_1_15_2 = mc_data("1.15.2")?;
let dim_is_int_1_15 = data_1_15_2.support_feature("dimensionIsAnInt")?;
assert_eq!(dim_is_int_1_15, serde_json::Value::Bool(true));
// Check the same feature in 1.18.2
let dim_is_int_1_18 = data_1_18_2.support_feature("dimensionIsAnInt")?;
assert_eq!(dim_is_int_1_18, serde_json::Value::Bool(false));
// Check a feature with a value
let metadata_index = data_1_18_2.support_feature("metadataIxOfItem")?;
assert_eq!(metadata_index, serde_json::Value::Number(8.into())); // Value might change in data updates
// --- Listing Supported Versions ---
let pc_versions = supported_versions(Edition::Pc)?;
println!("\nSupported PC Versions (Oldest to Newest):");
// Print first 5 and last 5 for brevity
for v in pc_versions.iter().take(5) {
println!(" - {}", v);
}
println!("...");
for v in pc_versions.iter().rev().take(5).rev() {
println!(" - {}", v);
}
// let bedrock_versions = supported_versions(Edition::Bedrock)?;
// println!("\nSupported Bedrock Versions: {:?}", bedrock_versions);
// --- Accessing Raw Data (Example: Recipes) ---
if let Some(recipes) = data_1_18_2.recipes.as_ref() {
// recipes is a serde_json::Value, access it as needed
if let Some(crafting_table_recipes) = recipes.get("minecraft:crafting_table") {
println!("\nFound {} recipes for crafting_table", crafting_table_recipes.as_array().map_or(0, |a| a.len()));
}
}
Ok(())
}
```
## License
Licensed under the MIT License. See the [LICENSE](LICENSE) file for details.