Skip to main content

airi_codegen/
packets.rs

1use indexmap::IndexMap;
2
3use heck::ToShoutySnekCase;
4use proc_macro2::TokenStream;
5use quote::format_ident;
6use quote::quote;
7
8pub fn build() -> TokenStream {
9    let packet_data: IndexMap<String, IndexMap<String, IndexMap<String, i32>>> =
10        serde_json::from_slice(include_bytes!("../assets/packets.json")).unwrap();
11
12    // packet -> (dir,state,id)
13    let mut seen_packets: IndexMap<String, (String, String, i32)> = IndexMap::new();
14
15    for (state, dirs) in packet_data {
16        for (dir, packets) in dirs {
17            for (mut packet, id) in packets {
18                packet = packet.strip_prefix("minecraft:").unwrap().to_owned();
19                insert_recurse(&mut seen_packets, packet, &dir, &state, id);
20            }
21        }
22    }
23
24    let mut packet_declarations = Vec::new();
25
26    for (packet, (_, _, id)) in seen_packets {
27        let var_name = format_ident!("{}", packet.replace('/', "_").TO_SHOUTY_SNEK_CASE());
28        packet_declarations.push(quote! { pub const #var_name: i32 = #id; });
29    }
30
31    quote! {
32        #(#packet_declarations)*
33    }
34}
35
36// this was so much more work than necessary omfg
37fn insert_recurse(
38    seen_packets: &mut IndexMap<String, (String, String, i32)>,
39    mut packet: String,
40    dir: &String,
41    state: &String,
42    id: i32,
43) {
44    // shift_remove is O(n) but maintains order
45    if let Some(other) = seen_packets.shift_remove(&packet) {
46        if &other.0 == dir {
47            packet.push('_');
48            insert_recurse(
49                seen_packets,
50                packet.clone() + &other.1,
51                &other.0,
52                &other.1,
53                other.2,
54            );
55            insert_recurse(seen_packets, packet.clone() + state, dir, state, id);
56        } else {
57            insert_recurse(
58                seen_packets,
59                other.0.clone() + "_" + &packet,
60                &other.0,
61                &other.1,
62                other.2,
63            );
64            insert_recurse(seen_packets, dir.clone() + "_" + &packet, dir, state, id);
65        }
66    } else {
67        seen_packets.insert(packet.clone(), (dir.clone(), state.clone(), id));
68    }
69}