Pumpkin/pumpkin-codegen/src/wit/java_packet.rs
Alexander Medvedev 3629f43dcc fix: disable cave carver for now
fixes some issues
2026-05-23 16:36:08 +02:00

127 lines
4.2 KiB
Rust

use crate::wit::utils::map_type;
use heck::ToKebabCase;
use semver::Version;
use std::{fs, path::Path};
use syn::{Fields, Item};
use wit_encoder::{
Field, Interface, Package, PackageName, Record, Type as WitType, TypeDef, TypeDefKind, Variant,
VariantCase,
};
pub fn build() -> String {
let mut package = Package::new(PackageName::new(
"pumpkin",
"plugin",
Some(Version::new(0, 1, 0)),
));
let mut interface = Interface::new("java-packets");
interface.use_type("uuid", "uuid", None);
let mut serverbound_variant = Variant::empty();
let mut clientbound_variant = Variant::empty();
// Process serverbound packets
process_packets(
"../pumpkin-protocol/src/java/server/play",
&mut interface,
&mut serverbound_variant,
);
// Process clientbound packets
process_packets(
"../pumpkin-protocol/src/java/client/play",
&mut interface,
&mut clientbound_variant,
);
interface.type_def(TypeDef::new(
"serverbound-packet",
TypeDefKind::Variant(serverbound_variant),
));
interface.type_def(TypeDef::new(
"clientbound-packet",
TypeDefKind::Variant(clientbound_variant),
));
package.interface(interface);
package.to_string()
}
fn process_packets(dir: &str, interface: &mut Interface, variant: &mut Variant) {
let paths = fs::read_dir(dir).expect("Failed to read packet directory");
let mut sorted_paths: Vec<_> = paths
.map(|e| e.expect("Failed to read entry").path())
.collect();
sorted_paths.sort();
for path in sorted_paths {
if path.extension().is_some_and(|ext| ext == "rs")
&& path.file_name().is_some_and(|name| name != "mod.rs")
{
parse_packet_file(&path, interface, variant);
}
}
}
fn parse_packet_file(path: &Path, interface: &mut Interface, variant: &mut Variant) {
let content = fs::read_to_string(path).expect("Failed to read file");
let file = syn::parse_file(&content).expect("Failed to parse file");
for item in file.items {
if let Item::Struct(s) = item {
// Only process structs with #[java_packet] attribute
if !s
.attrs
.iter()
.any(|attr| attr.path().is_ident("java_packet"))
{
continue;
}
let struct_name = s.ident.to_string();
let mut fields_list = Vec::new();
if let Fields::Named(fields) = s.fields {
for field in fields.named {
let type_name = match &field.ty {
syn::Type::Path(p) => p.path.segments.last().unwrap().ident.to_string(),
syn::Type::Reference(r) => match &*r.elem {
syn::Type::Slice(s) => match &*s.elem {
syn::Type::Path(p) => {
p.path.segments.last().unwrap().ident.to_string()
}
_ => String::new(),
},
syn::Type::Path(p) => p.path.segments.last().unwrap().ident.to_string(),
_ => String::new(),
},
_ => String::new(),
};
if type_name == "DynamicRecipe" {
continue;
}
let field_name = field.ident.as_ref().unwrap().to_string().to_kebab_case();
let field_type = map_type(&field.ty);
fields_list.push(Field::new(field_name, field_type));
}
}
let wit_name = struct_name.to_kebab_case();
if !fields_list.is_empty() {
interface.type_def(TypeDef::new(
wit_name.clone(),
TypeDefKind::Record(Record::new(fields_list)),
));
variant.case(VariantCase::value(
wit_name.clone(),
WitType::named(wit_name),
));
} else {
variant.case(VariantCase::empty(wit_name));
}
}
}
}