Parses the Types Section of the protocol.json

pull/5/head
Wyatt Herkamp 2 years ago
parent 6637b25e77
commit 1452ced77f

@ -36,7 +36,7 @@ impl Items {
Ok(self Ok(self
.items_array()? .items_array()?
.into_iter() .into_iter()
.map(|i| (i.id.clone(), i)) .map(|i| (i.id, i))
.collect()) .collect())
} }
} }

@ -21,10 +21,11 @@ mod entities;
mod foods; mod foods;
mod items; mod items;
mod loot; mod loot;
mod protocol;
mod recipes; mod recipes;
mod versions; mod versions;
mod protocol;
use crate::api::protocol::Protocol;
pub use biomes::*; pub use biomes::*;
pub use blocks::*; pub use blocks::*;
pub use enchantments::*; pub use enchantments::*;
@ -34,7 +35,6 @@ pub use items::*;
pub use loot::*; pub use loot::*;
pub use recipes::*; pub use recipes::*;
pub use versions::*; pub use versions::*;
use crate::api::protocol::Protocol;
/// A type wrapping access to all the metadata /// A type wrapping access to all the metadata
/// about the selected minecraft version /// about the selected minecraft version

@ -1,12 +1,12 @@
use std::sync::Arc;
use crate::data::{get_version_specific_file, PROTOCOL_FILE}; use crate::data::{get_version_specific_file, PROTOCOL_FILE};
use crate::{DataError, DataResult};
use crate::models::version::Version; use crate::models::version::Version;
use crate::{DataError, DataResult};
use std::sync::Arc;
pub struct Protocol { pub struct Protocol {
version: Arc<Version>, version: Arc<Version>,
} }
impl Protocol{ impl Protocol {
pub fn new(version: Arc<Version>) -> Self { pub fn new(version: Arc<Version>) -> Self {
Self { version } Self { version }
} }
@ -14,4 +14,4 @@ impl Protocol{
let content = get_version_specific_file(&self.version, PROTOCOL_FILE)?; let content = get_version_specific_file(&self.version, PROTOCOL_FILE)?;
serde_json::from_str(&content).map_err(DataError::from) serde_json::from_str(&content).map_err(DataError::from)
} }
} }

@ -9,9 +9,9 @@ mod entities;
mod foods; mod foods;
mod items; mod items;
mod loot; mod loot;
mod protocol;
mod recipes; mod recipes;
mod versions; mod versions;
mod protocol;
fn get_api(version: Version) -> Api { fn get_api(version: Version) -> Api {
Api::new(version) Api::new(version)

@ -1,11 +1,11 @@
use std::sync::Arc;
use crate::Api;
use crate::api::protocol::Protocol; use crate::api::protocol::Protocol;
use crate::api::tests::get_test_versions; use crate::api::tests::get_test_versions;
use crate::models::protocol::PacketDataType; use crate::models::protocol::PacketDataType;
use crate::Api;
use std::sync::Arc;
#[test] #[test]
pub fn simple_test(){ pub fn simple_test() {
let versions = get_test_versions(); let versions = get_test_versions();
for x in versions { for x in versions {
let protocol = Protocol::new(Arc::new(x)); let protocol = Protocol::new(Arc::new(x));
@ -13,10 +13,10 @@ pub fn simple_test(){
for protocol in protocol1.types.types { for protocol in protocol1.types.types {
match protocol { match protocol {
PacketDataType::Other(other, data) => { PacketDataType::Other(other, data) => {
println!("{:?} data {:?}", other,data); println!("{:?} data {:?}", other, data);
} }
_ => {} _ => {}
} }
} }
} }
} }

@ -29,7 +29,7 @@ pub fn latest_stable() -> DataResult<Version> {
.into_iter() .into_iter()
.filter_map(|v| { .filter_map(|v| {
let version_string = v.clone(); let version_string = v.clone();
let mut parts = version_string.split("."); let mut parts = version_string.split('.');
Some(( Some((
v, v,

@ -39,9 +39,9 @@ pub static VERSIONS_FILE: &str = "versions";
pub fn get_common_file(filename: &str) -> DataResult<String> { pub fn get_common_file(filename: &str) -> DataResult<String> {
MINECRAFT_DATA MINECRAFT_DATA
.get_file(format!("pc/common/{}.json", filename)) .get_file(format!("pc/common/{}.json", filename))
.ok_or(DataError::NotFoundError(filename.to_string()))? .ok_or_else(||DataError::NotFoundError(filename.to_string()))?
.contents_utf8() .contents_utf8()
.ok_or(DataError::InvalidEncodingError(filename.to_string())) .ok_or_else(||DataError::InvalidEncodingError(filename.to_string()))
.map(|d| d.to_string()) .map(|d| d.to_string())
} }
@ -50,12 +50,12 @@ pub fn get_version_specific_file(version: &Version, filename: &str) -> DataResul
let path = get_path(version, filename)?; let path = get_path(version, filename)?;
MINECRAFT_DATA MINECRAFT_DATA
.get_file(format!("{}/{}.json", path, filename)) .get_file(format!("{}/{}.json", path, filename))
.ok_or(DataError::NotFoundError(format!( .ok_or_else(||DataError::NotFoundError(format!(
"{}/{}", "{}/{}",
version.minecraft_version, filename version.minecraft_version, filename
)))? )))?
.contents_utf8() .contents_utf8()
.ok_or(DataError::InvalidEncodingError(filename.to_string())) .ok_or_else(||DataError::InvalidEncodingError(filename.to_string()))
.map(|d| d.to_string()) .map(|d| d.to_string())
} }
@ -67,19 +67,19 @@ pub fn get_path(version: &Version, filename: &str) -> DataResult<String> {
PATHS PATHS
.pc .pc
.get(&version.minecraft_version) .get(&version.minecraft_version)
.ok_or(DataError::NotFoundError(version.minecraft_version.clone()))? .ok_or_else(||DataError::NotFoundError(version.minecraft_version.clone()))?
.get(filename) .get(filename)
.cloned() .cloned()
.ok_or(DataError::NotFoundError(filename.to_string())) .ok_or_else(||DataError::NotFoundError(filename.to_string()))
} }
/// Returns the parsed data paths /// Returns the parsed data paths
fn get_datapaths() -> DataResult<Datapaths> { fn get_datapaths() -> DataResult<Datapaths> {
let content = MINECRAFT_DATA let content = MINECRAFT_DATA
.get_file("dataPaths.json") .get_file("dataPaths.json")
.ok_or(DataError::NotFoundError("dataPaths.json".to_string()))? .ok_or_else(||DataError::NotFoundError("dataPaths.json".to_string()))?
.contents_utf8() .contents_utf8()
.ok_or(DataError::InvalidEncodingError( .ok_or_else(||DataError::InvalidEncodingError(
"dataPaths.json".to_string(), "dataPaths.json".to_string(),
))?; ))?;
serde_json::from_str::<Datapaths>(content).map_err(DataError::from) serde_json::from_str::<Datapaths>(content).map_err(DataError::from)

@ -7,6 +7,6 @@ pub mod entity;
pub mod entity_loot; pub mod entity_loot;
pub mod food; pub mod food;
pub mod item; pub mod item;
pub mod protocol;
pub mod recipe; pub mod recipe;
pub mod version; pub mod version;
pub mod protocol;

@ -1,8 +1,9 @@
pub mod types; pub mod types;
pub use types::{NativeType, PacketDataTypes, PacketDataType,BitField};
use serde::Deserialize;
pub use types::{BitField, NativeType, PacketDataType, PacketDataTypes};
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Protocol { pub struct Protocol {
pub types: PacketDataTypes, pub types: PacketDataTypes,
} }

@ -1,13 +1,14 @@
use std::collections::HashMap;
use std::fmt::Formatter;
use serde::{Deserialize, Deserializer};
use serde::de::Visitor; use serde::de::Visitor;
use serde::{Deserialize, Deserializer};
use serde_json::Value; use serde_json::Value;
use std::borrow::{Cow};
use std::collections::HashMap;
#[derive(Deserialize)]
pub struct BitField { pub struct BitField {
name: String, pub name: String,
size: usize, pub size: i64,
signed: bool, pub signed: bool,
} }
/// These data types should be available in every version. /// These data types should be available in every version.
@ -17,7 +18,7 @@ pub enum NativeType {
/// Please read the following link for information on parsing https://wiki.vg/Protocol#VarInt_and_VarLong /// Please read the following link for information on parsing https://wiki.vg/Protocol#VarInt_and_VarLong
VarInt, VarInt,
PString { PString {
count_type: Box<NativeType> count_type: Box<NativeType>,
}, },
Buffer { Buffer {
count_type: Box<NativeType>, count_type: Box<NativeType>,
@ -37,10 +38,10 @@ pub enum NativeType {
// Optional<MinecraftPacketDataType> // Optional<MinecraftPacketDataType>
Option(Box<PacketDataType>), Option(Box<PacketDataType>),
EntityMetadataLoop { EntityMetadataLoop {
end_val: i32, end_val: i64,
metadata_type: Box<NativeType>, metadata_type: Box<PacketDataType>,
}, },
TopBitSetTerminatedArray(Box<NativeType>), TopBitSetTerminatedArray(Box<PacketDataType>),
BitField(Vec<BitField>), BitField(Vec<BitField>),
// A set of Name and The Type // A set of Name and The Type
Container(Vec<(String, Box<PacketDataType>)>), Container(Vec<(String, Box<PacketDataType>)>),
@ -61,66 +62,37 @@ pub enum NativeType {
impl NativeType { impl NativeType {
pub fn contains_type(name: &str) -> bool { pub fn contains_type(name: &str) -> bool {
match name { matches!(name, "varint" | "pstring" | "buffer" | "bool" | "u8" | "u16" | "u32" | "u64" | "i8" | "i16" | "i32" | "i64" | "f32" | "f64" | "uuid" | "option" | "entityMetadataLoop" | "topbitsetterminatedarray" | "bitfield" | "container" | "switch" | "void" | "array" | "restbuffer" | "nbt" | "optionalnbt")
"varint" => true,
"pstring" => true,
"buffer" => true,
"bool" => true,
"u8" => true,
"u16" => true,
"u32" => true,
"u64" => true,
"i8" => true,
"i16" => true,
"i32" => true,
"i64" => true,
"f32" => true,
"f64" => true,
"uuid" => true,
"option" => true,
"entitymetadataloop" => true,
"topbitsetterminatedarray" => true,
"bitfield" => true,
"container" => true,
"switch" => true,
"void" => true,
"array" => true,
"restbuffer" => true,
"nbt" => true,
"optionalnbt" => true,
_ => false,
}
} }
pub fn new(name: &str, layout: Option<Value>) -> Option<Self> { pub fn new(name: &str, layout: Cow<'_, Value>) -> Option<Self> {
match name { match name {
"varint" => Some(NativeType::VarInt), "varint" => Some(NativeType::VarInt),
"pstring" => { "pstring" => {
if let Some(layout) = layout { if let Value::Object(mut obj) = layout.into_owned() {
if let Some(value) = &layout.as_object().unwrap().get("countType") { if let Value::String(count_type) = obj.remove("countType").unwrap_or_default() {
if let Some(count_type) = NativeType::new(value.as_str().unwrap(), None) { if let Some(count_type) =
Some(NativeType::PString { NativeType::new(&count_type, Cow::Owned(Value::Null)) {
return Some(NativeType::PString {
count_type: Box::new(count_type), count_type: Box::new(count_type),
}) });
} else {
None
} }
} else {
None
} }
} else {
None
} }
None
} }
"buffer" => { "buffer" => {
if let Some(layout) = layout { if let Value::Object(mut obj) = layout.into_owned() {
if let Some(count_type) = NativeType::new(&layout["countType"].as_str().unwrap(), None) { if let Value::String(count_type) = obj.remove("countType").unwrap_or_default() {
Some(NativeType::Buffer { if let Some(count_type) =
count_type: Box::new(count_type), NativeType::new(&count_type, Cow::Owned(Value::Null))
}) {
} else { return Some(NativeType::PString {
None count_type: Box::new(count_type),
});
}
} }
} else { None } }
None
} }
"bool" => Some(NativeType::Bool), "bool" => Some(NativeType::Bool),
"u8" => Some(NativeType::U8), "u8" => Some(NativeType::U8),
@ -134,137 +106,115 @@ impl NativeType {
"f32" => Some(NativeType::F32), "f32" => Some(NativeType::F32),
"f64" => Some(NativeType::F64), "f64" => Some(NativeType::F64),
"uuid" => Some(NativeType::Uuid), "uuid" => Some(NativeType::Uuid),
"option" => { "option" => Some(NativeType::Option(build_inner_type(layout.into_owned()))),
if let Some(layout) = layout { "entityMetadataLoop" => {
let option = layout.as_array().unwrap().get(1); match layout.into_owned() {
Value::Object(mut layout) => {
if let Some(option_type) = option { let end_val = layout
let key = option_type.as_str().unwrap(); .remove("endVal")
let value = PacketDataType::new(key, None).or(Self::new(key, None).and_then(|x| Some(PacketDataType::Native(x)))); .and_then(|v| v.as_i64())
Some(NativeType::Option(Box::new(value.unwrap()))) .unwrap_or_default();
} else { let inner_type = layout.remove("type").unwrap_or_default();
None let inner_type = build_inner_type(inner_type);
Some(NativeType::EntityMetadataLoop {
end_val,
metadata_type: inner_type,
})
} }
} else { _ => None,
None
}
}
"entitymetadataloop" => {
if let Some(layout) = layout {
if let Some(end_val) = layout["endVal"].as_i64() {
let value1 = layout["type"].as_array().unwrap();
if let Some(metadata_type) = NativeType::new(&value1.get(0).unwrap().to_string(), value1.get(1).cloned()) {
Some(NativeType::EntityMetadataLoop {
end_val: end_val as i32,
metadata_type: Box::new(metadata_type),
})
} else {
None
}
} else {
None
}
} else {
None
} }
} }
"topbitsetterminatedarray" => { "topbitsetterminatedarray" => {
if let Some(layout) = layout { if let Value::Object(mut layout) = layout.into_owned() {
if let Some(count_type) = NativeType::new(&layout["countType"].as_str().unwrap(), None) { let inner_type = layout.remove("type").unwrap_or_default();
Some(NativeType::TopBitSetTerminatedArray(Box::new(count_type))) let inner_type = build_inner_type(inner_type);
} else { return Some(NativeType::TopBitSetTerminatedArray(inner_type));
None
}
} else {
None
} }
None
} }
"bitfield" => { "bitfield" => {
if let Some(layout) = layout { if let Value::Array(bit_fields) = layout.into_owned() {
let bit_fields = layout.as_array().unwrap(); let bit_fields_vec = bit_fields
let mut bit_fields_vec = Vec::new(); .into_iter()
for bit_field in bit_fields { .map(|v| serde_json::from_value(v).unwrap())
if let Some(name) = bit_field["name"].as_str() { .collect();
if let Some(size) = bit_field["size"].as_i64() {
if let Some(signed) = bit_field["signed"].as_bool() {
bit_fields_vec.push(BitField {
name: name.to_string(),
size: size as usize,
signed: signed,
});
}
}
}
}
Some(NativeType::BitField(bit_fields_vec)) Some(NativeType::BitField(bit_fields_vec))
} else { } else {
None None
} }
} }
"container" => { "container" => {
if let Some(layout) = layout { if let Value::Array(containers) = layout.into_owned() {
let containers = layout.as_array().unwrap(); let containers_vec = containers
let mut containers_vec = Vec::new(); .into_iter()
for container in containers { .map(|v| {
if let Some(name) = container["name"].as_str() { if let Value::Object(mut obj) = v {
if let Some(type_) = container["type"].as_str() { if let Some(name) = obj.remove("name") {
containers_vec.push((name.to_string(), Box::new(PacketDataType::new(type_, None).or(Self::new(type_, None). let name = name.to_string();
and_then(|x| Some(PacketDataType::Native(x)))).unwrap()))); let inner_type = obj.remove("type").unwrap_or_default();
let inner_type = build_inner_type(inner_type);
(name, inner_type)
} else {
let inner_type = obj.remove("type").unwrap_or_default();
let inner_type = build_inner_type(inner_type);
(String::new(), inner_type)
}
} else {
panic!("Container is not an object");
} }
} })
} .collect();
Some(NativeType::Container(containers_vec)) Some(NativeType::Container(containers_vec))
} else { } else {
None None
} }
} }
"switch" => { "switch" => {
if let Some(layout) = layout { if let Value::Object(mut layout) = layout.into_owned() {
if let Some(name) = layout["compareTo"].as_str() { return Some(NativeType::Switch {
if let Some(fields) = layout["fields"].as_object() { compare_to: layout.remove("compareTo").unwrap().to_string(),
let fields = fields.iter().map(|(key, v)| { fields: layout
(key.to_string(), v.to_string()) .remove("fields")
}).collect(); .and_then(|v| {
return Some(NativeType::Switch { if let Value::Object(fields) = v {
compare_to: name.to_string(), Some(
fields: fields, fields
default: None, .into_iter()
}); .map(|(k, v)| (k, v.to_string()))
} .collect(),
} )
} else {
None
}
})
.unwrap_or_default(),
default: layout.remove("default").map(|v| v.to_string()),
});
} }
None None
} }
"void" => Some(NativeType::Void), "void" => Some(NativeType::Void),
"array" => { "array" => {
if let Some(layout) = layout { if let Value::Object(mut obj) = layout.into_owned() {
let value = layout.as_object().unwrap(); let value = NativeType::new(
if let Some(count_type) = NativeType::new(&value.get("countType").unwrap().as_str().unwrap(), None) { obj.remove("countType")
let type_ = value.get("type").unwrap(); .unwrap_or_default()
if let Some(type_) = &type_.as_str() { .as_str()
return Some(NativeType::Array { .unwrap(),
count_type: Box::new(count_type), Cow::Owned(Value::Null),
array_type: Box::new(PacketDataType::new(type_, None).or(Self::new(type_, None). );
and_then(|x| Some(PacketDataType::Native(x)))).unwrap()), let inner_type = build_inner_type(obj.remove("type").unwrap_or_default());
}); if let Some(v) = value {
} else if let Some(array) = type_.as_array() { return Some(NativeType::Array {
let key = array.get(0).unwrap().as_str().unwrap(); count_type: Box::new(v),
if let Some(inner_type) = PacketDataType::new(key, array.get(1).cloned()). array_type: inner_type,
or(Self::new(key, array.get(1).cloned()).and_then(|x| Some(PacketDataType::Native(x)))) { });
return Some(NativeType::Array {
count_type: Box::new(count_type),
array_type: Box::new(inner_type),
});
}else{
println!("Could not parse array type: {}", key);
}
}
}else{
return None;
} }
} }
return None; None
} }
"restbuffer" => Some(NativeType::RestBuffer), "restbuffer" => Some(NativeType::RestBuffer),
@ -275,6 +225,48 @@ impl NativeType {
} }
} }
#[inline]
fn build_inner_type(value: Value) -> Box<PacketDataType> {
match value {
Value::String(simple_type) => {
return if let Some(simple_type) = NativeType::new(&simple_type, Cow::Owned(Value::Null))
{
Box::new(PacketDataType::Native(simple_type))
} else {
// Probably a reference to a built type
Box::new(PacketDataType::Other(simple_type, Value::Null))
};
}
Value::Array(mut array) => {
if array.len() != 2 {
return Box::new(PacketDataType::Other(String::new(), Value::Array(array)));
}
let inner_value = Cow::Owned(array.pop().unwrap_or_default());
let key = array.pop().unwrap();
if let Value::String(key) = &key {
let value = PacketDataType::new(key, Cow::clone(&inner_value)).or_else(|| {
let option = NativeType::new(key, inner_value.clone());
option.map(PacketDataType::Native)
});
if let Some(value) = value {
Box::new(value)
} else {
Box::new(PacketDataType::Other(
key.to_string(),
inner_value.into_owned(),
))
}
} else {
Box::new(PacketDataType::Other(
key.to_string(),
inner_value.into_owned(),
))
}
}
v => Box::new(PacketDataType::Other(String::new(), v)),
}
}
pub enum PacketDataType { pub enum PacketDataType {
// Just a pure native type // Just a pure native type
Native(NativeType), Native(NativeType),
@ -287,29 +279,29 @@ pub enum PacketDataType {
} }
impl PacketDataType { impl PacketDataType {
pub fn new(key: &str, value: Option<Value>) -> Option<Self> { pub fn new(key: &str, value: Cow<'_, Value>) -> Option<Self> {
if !NativeType::contains_type(&key) { if !NativeType::contains_type(key) {
let value = value.unwrap_or_default(); match value.into_owned() {
if value.is_string() { Value::String(string) => Some(PacketDataType::UnknownNativeType(string)),
Some(PacketDataType::UnknownNativeType(key.to_string())) Value::Array(mut array) => {
} else if let Some(array) = value.as_array() { if array.len() != 2 {
if let Some(name) = array.get(0) { return Some(PacketDataType::Other(key.to_string(), Value::Array(array)));
if let Some(name) = name.as_str() { }
let option = value.get(1).cloned();
let other_type = NativeType::new(&name, option.clone()); let inner_type_values = array.pop().unwrap_or_default();
if let Some(type_) = other_type { let inner_type_name = array.pop().unwrap();
if let Value::String(inner_type_name) = inner_type_name {
return if let Some(type_) =
NativeType::new(&inner_type_name, Cow::Borrowed(&inner_type_values))
{
Some(PacketDataType::Built(type_)) Some(PacketDataType::Built(type_))
} else { } else {
Some(PacketDataType::Other(name.to_string(), option.unwrap_or_default())) Some(PacketDataType::Other(inner_type_name, inner_type_values))
} };
} else {
Some(PacketDataType::Other(key.to_string(), value))
} }
} else {
None None
} }
} else { _ => None,
Some(PacketDataType::Other(key.to_string(), value))
} }
} else { } else {
None None
@ -323,7 +315,7 @@ pub struct PacketDataTypes {
use std::fmt; use std::fmt;
use serde::de::{self, SeqAccess, MapAccess}; use serde::de::{MapAccess};
impl<'de> Deserialize<'de> for PacketDataTypes { impl<'de> Deserialize<'de> for PacketDataTypes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@ -339,7 +331,6 @@ impl<'de> Deserialize<'de> for PacketDataTypes {
formatter.write_str("struct PacketDataTypes") formatter.write_str("struct PacketDataTypes")
} }
fn visit_map<V>(self, mut map: V) -> Result<PacketDataTypes, V::Error> fn visit_map<V>(self, mut map: V) -> Result<PacketDataTypes, V::Error>
where where
V: MapAccess<'de>, V: MapAccess<'de>,
@ -347,7 +338,7 @@ impl<'de> Deserialize<'de> for PacketDataTypes {
let mut types = Vec::new(); let mut types = Vec::new();
while let Some(key) = map.next_key::<String>()? { while let Some(key) = map.next_key::<String>()? {
let value = map.next_value::<Value>()?; let value = map.next_value::<Value>()?;
if let Some(ty) = PacketDataType::new(&key, Some(value)) { if let Some(ty) = PacketDataType::new(&key, Cow::Owned(value)) {
types.push(ty); types.push(ty);
} }
} }
@ -357,4 +348,4 @@ impl<'de> Deserialize<'de> for PacketDataTypes {
deserializer.deserialize_map(PacketDataTypesVisitor) deserializer.deserialize_map(PacketDataTypesVisitor)
} }
} }

Loading…
Cancel
Save