Fix packet ids
This commit is contained in:
@@ -15,3 +15,4 @@ serde = "1.0.120"
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
handlebars = "3.5.2"
|
handlebars = "3.5.2"
|
||||||
heck = "0.3.2"
|
heck = "0.3.2"
|
||||||
|
linked-hash-map = { version = "0.5.4", features = ["serde_impl"] }
|
||||||
|
@@ -1,37 +1,38 @@
|
|||||||
|
use linked_hash_map::LinkedHashMap;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Protocol {
|
pub struct Protocol {
|
||||||
handshaking: ProtocolState,
|
pub handshaking: ProtocolState,
|
||||||
status: ProtocolState,
|
pub status: ProtocolState,
|
||||||
login: ProtocolState,
|
pub login: ProtocolState,
|
||||||
#[serde(rename = "play")]
|
#[serde(rename = "play")]
|
||||||
game: ProtocolState,
|
pub game: ProtocolState,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ProtocolState {
|
pub struct ProtocolState {
|
||||||
to_client: ProtocolData,
|
pub to_client: ProtocolData,
|
||||||
to_server: ProtocolData,
|
pub to_server: ProtocolData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct ProtocolData {
|
pub struct ProtocolData {
|
||||||
types: HashMap<String, Vec<Data>>,
|
pub types: LinkedHashMap<String, Vec<Data>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum Data {
|
pub enum Data {
|
||||||
Type(String),
|
Type(String),
|
||||||
Container(Vec<Container>),
|
Container(Vec<Container>),
|
||||||
Mapper {
|
Mapper {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
mappings_type: String,
|
mappings_type: String,
|
||||||
mappings: HashMap<String, String>,
|
mappings: LinkedHashMap<String, String>,
|
||||||
},
|
},
|
||||||
Switch(Switch),
|
Switch(Switch),
|
||||||
List(Box<List>),
|
List(Box<List>),
|
||||||
@@ -40,13 +41,13 @@ enum Data {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum Container {
|
pub enum Container {
|
||||||
Value {
|
Value {
|
||||||
name: String,
|
name: String,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
data: Data,
|
data: Data,
|
||||||
},
|
},
|
||||||
Array {
|
List {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
data: Vec<Data>,
|
data: Vec<Data>,
|
||||||
@@ -55,7 +56,7 @@ enum Container {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum Switch {
|
pub enum Switch {
|
||||||
Empty {
|
Empty {
|
||||||
#[serde(rename = "compareTo")]
|
#[serde(rename = "compareTo")]
|
||||||
compare_to: String,
|
compare_to: String,
|
||||||
@@ -63,18 +64,18 @@ enum Switch {
|
|||||||
Value {
|
Value {
|
||||||
#[serde(rename = "compareTo")]
|
#[serde(rename = "compareTo")]
|
||||||
compare_to: String,
|
compare_to: String,
|
||||||
fields: HashMap<String, Data>,
|
fields: LinkedHashMap<String, Data>,
|
||||||
},
|
},
|
||||||
List {
|
List {
|
||||||
#[serde(rename = "compareTo")]
|
#[serde(rename = "compareTo")]
|
||||||
compare_to: String,
|
compare_to: String,
|
||||||
fields: HashMap<String, Vec<Data>>,
|
fields: LinkedHashMap<String, Vec<Data>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum List {
|
pub enum List {
|
||||||
Empty {
|
Empty {
|
||||||
#[serde(rename = "countType")]
|
#[serde(rename = "countType")]
|
||||||
count_type: String,
|
count_type: String,
|
||||||
@@ -85,7 +86,7 @@ enum List {
|
|||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
list_type: Data,
|
list_type: Data,
|
||||||
},
|
},
|
||||||
Array {
|
List {
|
||||||
#[serde(rename = "countType")]
|
#[serde(rename = "countType")]
|
||||||
count_type: String,
|
count_type: String,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
@@ -94,7 +95,7 @@ enum List {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct BitField {
|
pub struct BitField {
|
||||||
name: String,
|
name: String,
|
||||||
size: usize,
|
size: usize,
|
||||||
signed: bool,
|
signed: bool,
|
||||||
|
@@ -52,13 +52,15 @@ impl Display for Bound {
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Packet {
|
pub struct Packet {
|
||||||
|
pub id: u8,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub fields: Vec<Field>,
|
pub fields: Vec<Field>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Packet {
|
impl Packet {
|
||||||
pub fn new(name: impl ToString, fields: Vec<Field>) -> Packet {
|
pub fn new(id: u8, name: impl ToString, fields: Vec<Field>) -> Packet {
|
||||||
Packet {
|
Packet {
|
||||||
|
id,
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
fields,
|
fields,
|
||||||
}
|
}
|
||||||
|
@@ -2,12 +2,15 @@ mod data;
|
|||||||
|
|
||||||
use crate::data::input;
|
use crate::data::input;
|
||||||
use handlebars::*;
|
use handlebars::*;
|
||||||
use heck::SnakeCase;
|
use heck::{CamelCase, KebabCase, MixedCase, SnakeCase, TitleCase};
|
||||||
|
|
||||||
|
use crate::data::input::{Container, Data, ProtocolData, ProtocolState};
|
||||||
use crate::data::output;
|
use crate::data::output;
|
||||||
use crate::data::output::Bound;
|
use crate::data::output::{Bound, Packet, State};
|
||||||
|
use linked_hash_map::LinkedHashMap;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
@@ -31,10 +34,35 @@ pub fn main() {
|
|||||||
let protocol_data_file =
|
let protocol_data_file =
|
||||||
File::open(protocol_data_file_name).expect("Failed to open protocol data file");
|
File::open(protocol_data_file_name).expect("Failed to open protocol data file");
|
||||||
|
|
||||||
let protocol_data: input::Protocol =
|
let protocol_input: input::Protocol =
|
||||||
serde_json::from_reader(protocol_data_file).expect("Failed to parse protocol data");
|
serde_json::from_reader(protocol_data_file).expect("Failed to parse protocol data");
|
||||||
|
|
||||||
println!("{:#?}", protocol_data)
|
let protocols = vec![
|
||||||
|
(
|
||||||
|
transform_protocol_state(State::Handshake, &protocol_input.handshaking),
|
||||||
|
State::Handshake,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
transform_protocol_state(State::Status, &protocol_input.status),
|
||||||
|
State::Status,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
transform_protocol_state(State::Login, &protocol_input.login),
|
||||||
|
State::Login,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
transform_protocol_state(State::Game, &protocol_input.game),
|
||||||
|
State::Game,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (protocol, state) in protocols {
|
||||||
|
let file_name = format!("{}.rs", state.to_string().to_lowercase());
|
||||||
|
let file = File::create(file_name).expect("Failed to create file");
|
||||||
|
|
||||||
|
generate_rust_file(&protocol, &template_engine, &file)
|
||||||
|
.expect("Failed to generate rust file");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_template_engine() -> Handlebars<'static> {
|
fn create_template_engine() -> Handlebars<'static> {
|
||||||
@@ -68,13 +96,81 @@ fn create_template_engine() -> Handlebars<'static> {
|
|||||||
template_engine
|
template_engine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn transform_protocol_state(state: State, protocol_state: &ProtocolState) -> output::Protocol {
|
||||||
|
let server_bound_packets = transform_protocol_data(&protocol_state.to_server);
|
||||||
|
let client_bound_packets = transform_protocol_data(&protocol_state.to_client);
|
||||||
|
|
||||||
|
output::Protocol {
|
||||||
|
state,
|
||||||
|
server_bound_packets,
|
||||||
|
client_bound_packets,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transform_protocol_data(protocol_data: &ProtocolData) -> Vec<Packet> {
|
||||||
|
let mut packets = vec![];
|
||||||
|
|
||||||
|
let reversed_packet_ids = protocol_data
|
||||||
|
.types
|
||||||
|
.get("packet")
|
||||||
|
.and_then(|d| d.get(1))
|
||||||
|
.and_then(|d| match d {
|
||||||
|
Data::Container(data) => data.get(0),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.and_then(|c| match c {
|
||||||
|
Container::List { data, .. } => data.get(1),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.and_then(|d| match d {
|
||||||
|
Data::Mapper { mappings, .. } => Some(mappings),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.expect("Failed to get packet ids");
|
||||||
|
|
||||||
|
let packet_ids: HashMap<String, u8> = reversed_packet_ids
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| {
|
||||||
|
(
|
||||||
|
v.clone(),
|
||||||
|
u8::from_str_radix(k.trim_start_matches("0x"), 16).expect("Invalid packet id"),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (unformatted_name, data) in protocol_data.types.iter() {
|
||||||
|
if !unformatted_name.starts_with("packet_")
|
||||||
|
|| unformatted_name == "packet_legacy_server_list_ping"
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let no_prefix_name = unformatted_name.trim_start_matches("packet_");
|
||||||
|
|
||||||
|
let id = *packet_ids
|
||||||
|
.get(no_prefix_name)
|
||||||
|
.expect("Failed to get packet id");
|
||||||
|
let name = no_prefix_name.to_camel_case();
|
||||||
|
|
||||||
|
let packet = Packet {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
fields: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
packets.push(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
packets
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct GenerateContext<'a> {
|
struct GenerateContext<'a> {
|
||||||
packet_enum_name: String,
|
packet_enum_name: String,
|
||||||
packets: &'a Vec<output::Packet>,
|
packets: &'a Vec<output::Packet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_rust_file<W: Write>(
|
fn generate_rust_file<W: Write>(
|
||||||
protocol: &output::Protocol,
|
protocol: &output::Protocol,
|
||||||
template_engine: &Handlebars,
|
template_engine: &Handlebars,
|
||||||
mut writer: W,
|
mut writer: W,
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
|
{{~#if packets}}
|
||||||
pub enum {{protocol_enum_name}} {
|
pub enum {{packet_enum_name}} {
|
||||||
{{~#each packets as |p|}}
|
{{~#each packets as |p|}}
|
||||||
{{p.name}}{{#if p.fields}}({{p.name}}){{/if}}{{#unless @last}},{{/unless}}
|
{{p.name}}{{#if p.fields}}({{p.name}}){{/if}}{{#unless @last}},{{/unless}}
|
||||||
{{~/each}}
|
{{~/each}}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl {{protocol_enum_name}} {
|
impl {{packet_enum_name}} {
|
||||||
pub fn get_type_id(&self) -> u8 {
|
pub fn get_type_id(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
{{~#each packets as |p|}}
|
{{~#each packets as |p|}}
|
||||||
Self::{{p.name}}{{#if p.fields}}(_){{/if}} => {{packet_id @index}}{{#unless @last}},{{/unless}}
|
Self::{{p.name}}{{#if p.fields}}(_){{/if}} => {{packet_id p.id}}{{#unless @last}},{{/unless}}
|
||||||
{{~/each}}
|
{{~/each}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ impl {{protocol_enum_name}} {
|
|||||||
pub fn decode<R: Read>(type_id: u8, reader: &mut R) -> Result<Self, DecodeError> {
|
pub fn decode<R: Read>(type_id: u8, reader: &mut R) -> Result<Self, DecodeError> {
|
||||||
match type_id {
|
match type_id {
|
||||||
{{~#each packets as |p|}}
|
{{~#each packets as |p|}}
|
||||||
{{@index}} => {
|
{{packet_id p.id}} => {
|
||||||
{{~#if p.fields}}
|
{{~#if p.fields}}
|
||||||
let {{snake_case p.name}} = {{p.name}}::decode(reader)?;
|
let {{snake_case p.name}} = {{p.name}}::decode(reader)?;
|
||||||
|
|
||||||
@@ -48,3 +48,4 @@ impl {{protocol_enum_name}} {
|
|||||||
}
|
}
|
||||||
{{/each~}}
|
{{/each~}}
|
||||||
}
|
}
|
||||||
|
{{~/if}}
|
Reference in New Issue
Block a user