Parses Types up to entityMetadataLoop
parent
b6507aae16
commit
6637b25e77
@ -0,0 +1,17 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use crate::data::{get_version_specific_file, PROTOCOL_FILE};
|
||||||
|
use crate::{DataError, DataResult};
|
||||||
|
use crate::models::version::Version;
|
||||||
|
|
||||||
|
pub struct Protocol {
|
||||||
|
version: Arc<Version>,
|
||||||
|
}
|
||||||
|
impl Protocol{
|
||||||
|
pub fn new(version: Arc<Version>) -> Self {
|
||||||
|
Self { version }
|
||||||
|
}
|
||||||
|
pub fn get_protocol(&self) -> DataResult<crate::models::protocol::Protocol> {
|
||||||
|
let content = get_version_specific_file(&self.version, PROTOCOL_FILE)?;
|
||||||
|
serde_json::from_str(&content).map_err(DataError::from)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use crate::Api;
|
||||||
|
use crate::api::protocol::Protocol;
|
||||||
|
use crate::api::tests::get_test_versions;
|
||||||
|
use crate::models::protocol::PacketDataType;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn simple_test(){
|
||||||
|
let versions = get_test_versions();
|
||||||
|
for x in versions {
|
||||||
|
let protocol = Protocol::new(Arc::new(x));
|
||||||
|
let protocol1 = protocol.get_protocol().unwrap();
|
||||||
|
for protocol in protocol1.types.types {
|
||||||
|
match protocol {
|
||||||
|
PacketDataType::Other(other, data) => {
|
||||||
|
println!("{:?} data {:?}", other,data);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
pub mod types;
|
||||||
|
pub use types::{NativeType, PacketDataTypes, PacketDataType,BitField};
|
||||||
|
use serde::Deserialize;
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Protocol {
|
||||||
|
pub types: PacketDataTypes,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,360 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Formatter;
|
||||||
|
use serde::{Deserialize, Deserializer};
|
||||||
|
use serde::de::Visitor;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
pub struct BitField {
|
||||||
|
name: String,
|
||||||
|
size: usize,
|
||||||
|
signed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// These data types should be available in every version.
|
||||||
|
/// However, they won't break anything if not present
|
||||||
|
/// This can also be known as the Native Types
|
||||||
|
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>
|
||||||
|
},
|
||||||
|
Buffer {
|
||||||
|
count_type: Box<NativeType>,
|
||||||
|
},
|
||||||
|
Bool,
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
Uuid,
|
||||||
|
// Optional<MinecraftPacketDataType>
|
||||||
|
Option(Box<PacketDataType>),
|
||||||
|
EntityMetadataLoop {
|
||||||
|
end_val: i32,
|
||||||
|
metadata_type: Box<NativeType>,
|
||||||
|
},
|
||||||
|
TopBitSetTerminatedArray(Box<NativeType>),
|
||||||
|
BitField(Vec<BitField>),
|
||||||
|
// A set of Name and The Type
|
||||||
|
Container(Vec<(String, Box<PacketDataType>)>),
|
||||||
|
Switch {
|
||||||
|
compare_to: String,
|
||||||
|
fields: HashMap<String, String>,
|
||||||
|
default: Option<String>,
|
||||||
|
},
|
||||||
|
Void,
|
||||||
|
Array {
|
||||||
|
count_type: Box<NativeType>,
|
||||||
|
array_type: Box<PacketDataType>,
|
||||||
|
},
|
||||||
|
RestBuffer,
|
||||||
|
NBT,
|
||||||
|
OptionalNBT,
|
||||||
|
}
|
||||||
|
|
||||||
|
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> {
|
||||||
|
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 {
|
||||||
|
count_type: Box::new(count_type),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"buffer" => {
|
||||||
|
if let Some(layout) = layout {
|
||||||
|
if let Some(count_type) = NativeType::new(&layout["countType"].as_str().unwrap(), None) {
|
||||||
|
Some(NativeType::Buffer {
|
||||||
|
count_type: Box::new(count_type),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else { None }
|
||||||
|
}
|
||||||
|
"bool" => Some(NativeType::Bool),
|
||||||
|
"u8" => Some(NativeType::U8),
|
||||||
|
"u16" => Some(NativeType::U16),
|
||||||
|
"u32" => Some(NativeType::U32),
|
||||||
|
"u64" => Some(NativeType::U64),
|
||||||
|
"i8" => Some(NativeType::I8),
|
||||||
|
"i16" => Some(NativeType::I16),
|
||||||
|
"i32" => Some(NativeType::I32),
|
||||||
|
"i64" => Some(NativeType::I64),
|
||||||
|
"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()) {
|
||||||
|
Some(NativeType::EntityMetadataLoop {
|
||||||
|
end_val: end_val as i32,
|
||||||
|
metadata_type: Box::new(metadata_type),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
} 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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
return Some(NativeType::Switch {
|
||||||
|
compare_to: name.to_string(),
|
||||||
|
fields: fields,
|
||||||
|
default: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
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()),
|
||||||
|
});
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
"restbuffer" => Some(NativeType::RestBuffer),
|
||||||
|
"nbt" => Some(NativeType::NBT),
|
||||||
|
"optionalnbt" => Some(NativeType::OptionalNBT),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PacketDataType {
|
||||||
|
// Just a pure native type
|
||||||
|
Native(NativeType),
|
||||||
|
// It was marked as "native" however, this enum does not have it
|
||||||
|
UnknownNativeType(String),
|
||||||
|
// This type is built from a native type
|
||||||
|
Built(NativeType),
|
||||||
|
|
||||||
|
Other(String, Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
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()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(PacketDataType::Other(key.to_string(), value))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(PacketDataType::Other(key.to_string(), value))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PacketDataTypes {
|
||||||
|
pub types: Vec<PacketDataType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use serde::de::{self, SeqAccess, MapAccess};
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for PacketDataTypes {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct PacketDataTypesVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for PacketDataTypesVisitor {
|
||||||
|
type Value = PacketDataTypes;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("struct PacketDataTypes")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn visit_map<V>(self, mut map: V) -> Result<PacketDataTypes, V::Error>
|
||||||
|
where
|
||||||
|
V: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
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)) {
|
||||||
|
types.push(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(PacketDataTypes { types })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_map(PacketDataTypesVisitor)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue