Add versions and items api
Signed-off-by: trivernis <trivernis@protonmail.com>pull/1/head
commit
e03e8adf1f
@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
@ -0,0 +1,3 @@
|
||||
[submodule "minecraft-data"]
|
||||
path = minecraft-data
|
||||
url = git@github.com:PrismarineJS/minecraft-data.git
|
@ -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…
Reference in New Issue