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
.items_array()?
.into_iter()
.map(|i| (i.id.clone(), i))
.map(|i| (i.id, i))
.collect())
}
}

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

@ -1,12 +1,12 @@
use std::sync::Arc;
use crate::data::{get_version_specific_file, PROTOCOL_FILE};
use crate::{DataError, DataResult};
use crate::models::version::Version;
use crate::{DataError, DataResult};
use std::sync::Arc;
pub struct Protocol {
version: Arc<Version>,
}
impl Protocol{
impl Protocol {
pub fn new(version: Arc<Version>) -> Self {
Self { version }
}

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

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

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

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

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

@ -1,8 +1,9 @@
pub mod types;
pub use types::{NativeType, PacketDataTypes, PacketDataType,BitField};
use serde::Deserialize;
pub use types::{BitField, NativeType, PacketDataType, PacketDataTypes};
#[derive(Deserialize)]
pub struct Protocol {
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::{Deserialize, Deserializer};
use serde_json::Value;
use std::borrow::{Cow};
use std::collections::HashMap;
#[derive(Deserialize)]
pub struct BitField {
name: String,
size: usize,
signed: bool,
pub name: String,
pub size: i64,
pub signed: bool,
}
/// 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
VarInt,
PString {
count_type: Box<NativeType>
count_type: Box<NativeType>,
},
Buffer {
count_type: Box<NativeType>,
@ -37,10 +38,10 @@ pub enum NativeType {
// Optional<MinecraftPacketDataType>
Option(Box<PacketDataType>),
EntityMetadataLoop {
end_val: i32,
metadata_type: Box<NativeType>,
end_val: i64,
metadata_type: Box<PacketDataType>,
},
TopBitSetTerminatedArray(Box<NativeType>),
TopBitSetTerminatedArray(Box<PacketDataType>),
BitField(Vec<BitField>),
// A set of Name and The Type
Container(Vec<(String, Box<PacketDataType>)>),
@ -61,66 +62,37 @@ pub enum NativeType {
impl NativeType {
pub fn contains_type(name: &str) -> bool {
match name {
"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> {
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")
}
pub fn new(name: &str, layout: Cow<'_, Value>) -> Option<Self> {
match name {
"varint" => Some(NativeType::VarInt),
"pstring" => {
if let Some(layout) = layout {
if let Some(value) = &layout.as_object().unwrap().get("countType") {
if let Some(count_type) = NativeType::new(value.as_str().unwrap(), None) {
Some(NativeType::PString {
if let Value::Object(mut obj) = layout.into_owned() {
if let Value::String(count_type) = obj.remove("countType").unwrap_or_default() {
if let Some(count_type) =
NativeType::new(&count_type, Cow::Owned(Value::Null)) {
return Some(NativeType::PString {
count_type: Box::new(count_type),
})
} else {
None
});
}
} else {
None
}
} else {
None
}
None
}
"buffer" => {
if let Some(layout) = layout {
if let Some(count_type) = NativeType::new(&layout["countType"].as_str().unwrap(), None) {
Some(NativeType::Buffer {
if let Value::Object(mut obj) = layout.into_owned() {
if let Value::String(count_type) = obj.remove("countType").unwrap_or_default() {
if let Some(count_type) =
NativeType::new(&count_type, Cow::Owned(Value::Null))
{
return Some(NativeType::PString {
count_type: Box::new(count_type),
})
} else {
None
});
}
} else { None }
}
}
None
}
"bool" => Some(NativeType::Bool),
"u8" => Some(NativeType::U8),
@ -134,137 +106,115 @@ impl NativeType {
"f32" => Some(NativeType::F32),
"f64" => Some(NativeType::F64),
"uuid" => Some(NativeType::Uuid),
"option" => {
if let Some(layout) = layout {
let option = layout.as_array().unwrap().get(1);
if let Some(option_type) = option {
let key = option_type.as_str().unwrap();
let value = PacketDataType::new(key, None).or(Self::new(key, None).and_then(|x| Some(PacketDataType::Native(x))));
Some(NativeType::Option(Box::new(value.unwrap())))
} else {
None
}
} else {
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()) {
"option" => Some(NativeType::Option(build_inner_type(layout.into_owned()))),
"entityMetadataLoop" => {
match layout.into_owned() {
Value::Object(mut layout) => {
let end_val = layout
.remove("endVal")
.and_then(|v| v.as_i64())
.unwrap_or_default();
let inner_type = layout.remove("type").unwrap_or_default();
let inner_type = build_inner_type(inner_type);
Some(NativeType::EntityMetadataLoop {
end_val: end_val as i32,
metadata_type: Box::new(metadata_type),
end_val,
metadata_type: inner_type,
})
} else {
None
}
} else {
None
}
} else {
None
_ => None,
}
}
"topbitsetterminatedarray" => {
if let Some(layout) = layout {
if let Some(count_type) = NativeType::new(&layout["countType"].as_str().unwrap(), None) {
Some(NativeType::TopBitSetTerminatedArray(Box::new(count_type)))
} else {
None
if let Value::Object(mut layout) = layout.into_owned() {
let inner_type = layout.remove("type").unwrap_or_default();
let inner_type = build_inner_type(inner_type);
return Some(NativeType::TopBitSetTerminatedArray(inner_type));
}
} else {
None
}
}
"bitfield" => {
if let Some(layout) = layout {
let bit_fields = layout.as_array().unwrap();
let mut bit_fields_vec = Vec::new();
for bit_field in bit_fields {
if let Some(name) = bit_field["name"].as_str() {
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,
});
}
}
}
}
if let Value::Array(bit_fields) = layout.into_owned() {
let bit_fields_vec = bit_fields
.into_iter()
.map(|v| serde_json::from_value(v).unwrap())
.collect();
Some(NativeType::BitField(bit_fields_vec))
} else {
None
}
}
"container" => {
if let Some(layout) = layout {
let containers = layout.as_array().unwrap();
let mut containers_vec = Vec::new();
for container in containers {
if let Some(name) = container["name"].as_str() {
if let Some(type_) = container["type"].as_str() {
containers_vec.push((name.to_string(), Box::new(PacketDataType::new(type_, None).or(Self::new(type_, None).
and_then(|x| Some(PacketDataType::Native(x)))).unwrap())));
}
if let Value::Array(containers) = layout.into_owned() {
let containers_vec = containers
.into_iter()
.map(|v| {
if let Value::Object(mut obj) = v {
if let Some(name) = obj.remove("name") {
let name = name.to_string();
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))
} else {
None
}
}
"switch" => {
if let Some(layout) = layout {
if let Some(name) = layout["compareTo"].as_str() {
if let Some(fields) = layout["fields"].as_object() {
let fields = fields.iter().map(|(key, v)| {
(key.to_string(), v.to_string())
}).collect();
if let Value::Object(mut layout) = layout.into_owned() {
return Some(NativeType::Switch {
compare_to: name.to_string(),
fields: fields,
default: None,
});
}
compare_to: layout.remove("compareTo").unwrap().to_string(),
fields: layout
.remove("fields")
.and_then(|v| {
if let Value::Object(fields) = v {
Some(
fields
.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
}
"void" => Some(NativeType::Void),
"array" => {
if let Some(layout) = layout {
let value = layout.as_object().unwrap();
if let Some(count_type) = NativeType::new(&value.get("countType").unwrap().as_str().unwrap(), None) {
let type_ = value.get("type").unwrap();
if let Some(type_) = &type_.as_str() {
if let Value::Object(mut obj) = layout.into_owned() {
let value = NativeType::new(
obj.remove("countType")
.unwrap_or_default()
.as_str()
.unwrap(),
Cow::Owned(Value::Null),
);
let inner_type = build_inner_type(obj.remove("type").unwrap_or_default());
if let Some(v) = value {
return Some(NativeType::Array {
count_type: Box::new(count_type),
array_type: Box::new(PacketDataType::new(type_, None).or(Self::new(type_, None).
and_then(|x| Some(PacketDataType::Native(x)))).unwrap()),
count_type: Box::new(v),
array_type: inner_type,
});
} else if let Some(array) = type_.as_array() {
let key = array.get(0).unwrap().as_str().unwrap();
if let Some(inner_type) = PacketDataType::new(key, array.get(1).cloned()).
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),
@ -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 {
// Just a pure native type
Native(NativeType),
@ -287,29 +279,29 @@ pub enum PacketDataType {
}
impl PacketDataType {
pub fn new(key: &str, value: Option<Value>) -> Option<Self> {
if !NativeType::contains_type(&key) {
let value = value.unwrap_or_default();
if value.is_string() {
Some(PacketDataType::UnknownNativeType(key.to_string()))
} else if let Some(array) = value.as_array() {
if let Some(name) = array.get(0) {
if let Some(name) = name.as_str() {
let option = value.get(1).cloned();
let other_type = NativeType::new(&name, option.clone());
if let Some(type_) = other_type {
Some(PacketDataType::Built(type_))
} else {
Some(PacketDataType::Other(name.to_string(), option.unwrap_or_default()))
pub fn new(key: &str, value: Cow<'_, Value>) -> Option<Self> {
if !NativeType::contains_type(key) {
match value.into_owned() {
Value::String(string) => Some(PacketDataType::UnknownNativeType(string)),
Value::Array(mut array) => {
if array.len() != 2 {
return Some(PacketDataType::Other(key.to_string(), Value::Array(array)));
}
let inner_type_values = array.pop().unwrap_or_default();
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_))
} else {
Some(PacketDataType::Other(key.to_string(), value))
Some(PacketDataType::Other(inner_type_name, inner_type_values))
};
}
} else {
None
}
} else {
Some(PacketDataType::Other(key.to_string(), value))
_ => None,
}
} else {
None
@ -323,7 +315,7 @@ pub struct PacketDataTypes {
use std::fmt;
use serde::de::{self, SeqAccess, MapAccess};
use serde::de::{MapAccess};
impl<'de> Deserialize<'de> for PacketDataTypes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@ -339,7 +331,6 @@ impl<'de> Deserialize<'de> for PacketDataTypes {
formatter.write_str("struct PacketDataTypes")
}
fn visit_map<V>(self, mut map: V) -> Result<PacketDataTypes, V::Error>
where
V: MapAccess<'de>,
@ -347,7 +338,7 @@ impl<'de> Deserialize<'de> for PacketDataTypes {
let mut types = Vec::new();
while let Some(key) = map.next_key::<String>()? {
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);
}
}

Loading…
Cancel
Save