Add versions and items api

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/1/head
trivernis 3 years ago
commit e03e8adf1f
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

2
.gitignore vendored

@ -0,0 +1,2 @@
/target
Cargo.lock

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "minecraft-data"]
path = minecraft-data
url = git@github.com:PrismarineJS/minecraft-data.git

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CsvFileAttributes">
<option name="attributeMap">
<map>
<entry key="/src/data/mod.rs">
<value>
<Attribute>
<option name="separator" value=":" />
</Attribute>
</value>
</entry>
</map>
</option>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
</component>
</project>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/minecraft-data-rs.iml" filepath="$PROJECT_DIR$/.idea/minecraft-data-rs.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -0,0 +1,14 @@
[package]
name = "minecraft-data-rs"
version = "0.1.0"
authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
thiserror = "1.0.24"
serde_json = "1.0.64"
serde_derive = "1.0.125"
serde = "1.0.125"
include_dir = "0.6.0"

@ -0,0 +1 @@
Subproject commit 920d361e13351bbbd812c3bbd0ed05f4194b05fe

@ -0,0 +1,39 @@
use crate::data::{get_version_specific_file, ITEMS_FILE};
use crate::models::item::Item;
use crate::models::version::Version;
use crate::{DataError, DataResult};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::sync::Arc;
/// API to access item information
pub struct Items {
version: Arc<Version>,
}
impl Items {
pub fn new(version: Arc<Version>) -> Self {
Self { version }
}
/// Returns the items
pub fn items_array(&self) -> DataResult<Vec<Item>> {
let content = get_version_specific_file(&self.version, ITEMS_FILE)?;
serde_json::from_str::<Vec<Item>>(&*content).map_err(DataError::from)
}
/// Returns the items indexed by name
pub fn items_by_name(&self) -> DataResult<HashMap<String, Item>> {
Ok(HashMap::from_iter(
self.items_array()?.into_iter().map(|i| (i.name.clone(), i)),
))
}
/// Returns the items indexed by ID
pub fn items(&self) -> DataResult<HashMap<u32, Item>> {
Ok(HashMap::from_iter(
self.items_array()?.into_iter().map(|i| (i.id.clone(), i)),
))
}
}

@ -0,0 +1,24 @@
use crate::api::items::Items;
use crate::models::version::Version;
use std::sync::Arc;
#[cfg(test)]
mod tests;
pub mod items;
pub mod versions;
pub struct Api {
version: Arc<Version>,
items: Items,
}
impl Api {
pub fn new(version: Version) -> Self {
let version = Arc::new(version);
Self {
version: Arc::clone(&version),
items: Items::new(Arc::clone(&version)),
}
}
}

@ -0,0 +1,11 @@
use crate::api::tests::{get_api, get_test_versions};
#[test]
pub fn test_items_array() {
let versions = get_test_versions();
for version in versions {
let api = get_api(version);
assert_ne!(api.items.items_array().unwrap().len(), 0)
}
}

@ -0,0 +1,19 @@
use crate::api::versions::{available_versions, versions};
use crate::api::Api;
use crate::models::version::Version;
mod items;
mod versions;
fn get_api(version: Version) -> Api {
Api::new(version)
}
fn get_test_versions() -> Vec<Version> {
let available = available_versions().unwrap();
versions()
.unwrap()
.into_iter()
.filter(|v| available.contains(&v.minecraft_version))
.collect()
}

@ -0,0 +1,20 @@
use crate::api::versions::{latest_stable, versions, versions_by_minecraft_version};
#[test]
fn test_versions() {
let unordered_versions = versions().unwrap();
assert_ne!(unordered_versions.len(), 0)
}
#[test]
fn test_versions_by_minecraft_version() {
let versions = versions_by_minecraft_version().unwrap();
assert!(versions.get("1.16").is_some());
assert!(versions.get("1.14.12").is_none());
assert_eq!(versions.get("1.16.3").unwrap().major_version, "1.16")
}
#[test]
fn test_latest_stable_version() {
assert!(latest_stable().is_ok())
}

@ -0,0 +1,40 @@
use crate::data::{get_common_file, PROTOCOL_VERSIONS_FILE, VERSIONS_FILE};
use crate::models::version::Version;
use crate::{DataError, DataResult};
use std::collections::HashMap;
use std::iter::FromIterator;
/// Returns the unsorted list of versions
pub fn versions() -> DataResult<Vec<Version>> {
let content = get_common_file(PROTOCOL_VERSIONS_FILE)?;
let versions = serde_json::from_str::<Vec<Version>>(&*content)?;
Ok(versions)
}
/// Returns the versions indexed by minecraft version
pub fn versions_by_minecraft_version() -> DataResult<HashMap<String, Version>> {
let indexed_versions = HashMap::from_iter(
versions()?
.into_iter()
.map(|v| (v.minecraft_version.clone(), v)),
);
Ok(indexed_versions)
}
/// Returns the latest stable version (hardcoded at the moment)
pub fn latest_stable() -> DataResult<Version> {
versions_by_minecraft_version()?
.get("1.16.5")
.cloned()
.ok_or(DataError::NotFoundError("1.16.5".to_string()))
}
/// Returns a list of available version information
pub(crate) fn available_versions() -> DataResult<Vec<String>> {
Ok(get_common_file(VERSIONS_FILE)?
.split_whitespace()
.map(|s| s.to_string())
.collect())
}

@ -0,0 +1,61 @@
use crate::models::version::Version;
use crate::{DataError, DataResult};
use include_dir::Dir;
pub static MINECRAFT_DATA: Dir = include_dir::include_dir!("minecraft-data/data/pc");
pub static BIOMES_FILE: &str = "biomes.json";
pub static BLOCK_LOOT_FILE: &str = "blockLoot.json";
pub static BLOCKS_FILE: &str = "blocks.json";
pub static COMMANDS_FILE: &str = "commands.json";
pub static ENTITIES_FILE: &str = "entities.json";
pub static ENTITY_LOOT_FILE: &str = "entityLoot.json";
pub static ITEMS_FILE: &str = "items.json";
pub static LOGIN_PACKET_FILE: &str = "loginPacket.json";
pub static MATERIALS_FILE: &str = "materials.json";
pub static PROTOCOL_FILE: &str = "protocol.json";
pub static RECIPES_FILE: &str = "recipes.json";
pub static TINTS_FILE: &str = "tints.json";
// pub static VERSION_FILE: &str = "version.json";
pub static MAP_ICONS_FILE: &str = "mapIcons.json";
pub static PARTICLES_FILE: &str = "particles.json";
pub static PROTOCOL_VERSIONS_FILE: &str = "protocolVersions.json";
pub static VERSIONS_FILE: &str = "versions.json";
/// Returns the string encoded content of the common file
pub fn get_common_file(filename: &str) -> DataResult<String> {
MINECRAFT_DATA
.get_file(format!("common/{}", filename))
.ok_or(DataError::NotFoundError(filename.to_string()))?
.contents_utf8()
.ok_or(DataError::InvalidEncodingError(filename.to_string()))
.map(|d| d.to_string())
}
/// Returns the string encoded content of the version specific file
pub fn get_version_specific_file(version: &Version, filename: &str) -> DataResult<String> {
let search_folders = vec![
version.minecraft_version.clone(),
version.major_version.clone(),
version.major_first(),
version.previous_major(),
version.previous_major_first(),
];
println!("{:?}", search_folders);
let mut data = None;
for folder in search_folders {
data = MINECRAFT_DATA.get_file(format!("{}/{}", folder, filename));
if data.is_some() {
break;
}
}
data.ok_or(DataError::NotFoundError(format!(
"{}/{}",
version.minecraft_version, filename
)))?
.contents_utf8()
.ok_or(DataError::InvalidEncodingError(filename.to_string()))
.map(|d| d.to_string())
}

@ -0,0 +1,13 @@
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate include_dir;
pub mod api;
pub(crate) mod data;
pub mod models;
pub(crate) mod utils;
pub use utils::error::DataError;
pub use utils::error::DataResult;

@ -0,0 +1,15 @@
use serde_json::Value;
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all(deserialize = "camelCase", serialize = "snake_case"))]
pub struct Item {
pub id: u32,
pub display_name: String,
pub stack_size: u8,
pub enchant_categories: Option<Vec<String>>,
pub fixed_with: Option<Vec<String>>,
pub max_durability: Option<u32>,
pub name: String,
pub variations: Option<Value>,
pub durability: Option<u32>,
}

@ -0,0 +1,2 @@
pub mod item;
pub mod version;

@ -0,0 +1,28 @@
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all(deserialize = "camelCase", serialize = "snake_case"))]
pub struct Version {
pub version: i32,
pub minecraft_version: String,
pub major_version: String,
}
impl Version {
/// Returns the first version of the current major version
pub(crate) fn major_first(&self) -> String {
format!("{}.1", self.major_version)
}
/// Returns the previous major version
pub(crate) fn previous_major(&self) -> String {
let major = self.major_version.split('.').last().unwrap();
let major_num = major.parse::<i32>().unwrap();
self.major_version
.replace(major, format!("{}", major_num - 1).as_str())
}
/// Returns the first version of the previous major version
pub(crate) fn previous_major_first(&self) -> String {
format!("{}.1", self.previous_major())
}
}

@ -0,0 +1,19 @@
use std::io;
use thiserror::Error;
pub type DataResult<T> = Result<T, DataError>;
#[derive(Error, Debug)]
pub enum DataError {
#[error("IO Error: {0}")]
IOError(#[from] io::Error),
#[error("JSON Error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("Object {0} not found")]
NotFoundError(String),
#[error("Invalid encoding of file {0}")]
InvalidEncodingError(String),
}

@ -0,0 +1 @@
pub mod error;
Loading…
Cancel
Save