parse sound category at compile time

This commit is contained in:
Alexander Medvedev 2025-01-11 16:11:51 +01:00
parent 82386a57c4
commit c95b27eafb
14 changed files with 59 additions and 69 deletions

View File

@ -0,0 +1 @@
["MASTER","MUSIC","RECORDS","WEATHER","BLOCKS","HOSTILE","NEUTRAL","PLAYERS","AMBIENT","VOICE"]

View File

@ -1,5 +1,7 @@
use quote::quote;
use std::{env, fs, path::Path, process::Command}; use std::{env, fs, path::Path, process::Command};
use heck::ToPascalCase;
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use syn::Ident; use syn::Ident;
@ -9,6 +11,7 @@ mod packet;
mod particle; mod particle;
mod screen; mod screen;
mod sound; mod sound;
mod sound_category;
pub fn main() { pub fn main() {
write_generated_file(packet::build(), "packet.rs"); write_generated_file(packet::build(), "packet.rs");
@ -17,6 +20,19 @@ pub fn main() {
write_generated_file(sound::build(), "sound.rs"); write_generated_file(sound::build(), "sound.rs");
write_generated_file(chunk_status::build(), "chunk_status.rs"); write_generated_file(chunk_status::build(), "chunk_status.rs");
write_generated_file(game_event::build(), "game_event.rs"); write_generated_file(game_event::build(), "game_event.rs");
write_generated_file(sound_category::build(), "sound_category.rs");
}
pub fn array_to_tokenstream(array: Vec<String>) -> TokenStream {
let mut variants = TokenStream::new();
for item in array.iter() {
let name = ident(item.to_pascal_case());
variants.extend([quote! {
#name,
}]);
}
variants
} }
pub fn write_generated_file(content: TokenStream, out_file: &str) { pub fn write_generated_file(content: TokenStream, out_file: &str) {

View File

@ -1,23 +1,16 @@
use heck::ToPascalCase;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use crate::ident; use crate::array_to_tokenstream;
pub(crate) fn build() -> TokenStream { pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=assets/game_event.json"); println!("cargo:rerun-if-changed=assets/game_event.json");
let game_event: Vec<String> = let game_events: Vec<String> =
serde_json::from_str(include_str!("../../assets/game_event.json")) serde_json::from_str(include_str!("../../assets/game_event.json"))
.expect("Failed to parse game_event.json"); .expect("Failed to parse game_event.json");
let mut variants = TokenStream::new(); let variants = array_to_tokenstream(game_events);
for event in game_event.iter() {
let name = ident(event.to_pascal_case());
variants.extend([quote! {
#name,
}]);
}
quote! { quote! {
#[repr(u8)] #[repr(u8)]
pub enum GameEvent { pub enum GameEvent {

View File

@ -1,24 +1,15 @@
use heck::ToPascalCase;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use crate::ident; use crate::array_to_tokenstream;
pub(crate) fn build() -> TokenStream { pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=assets/particles.json"); println!("cargo:rerun-if-changed=assets/particles.json");
let particle: Vec<String> = serde_json::from_str(include_str!("../../assets/particles.json")) let particle: Vec<String> = serde_json::from_str(include_str!("../../assets/particles.json"))
.expect("Failed to parse particles.json"); .expect("Failed to parse particles.json");
let mut variants = TokenStream::new(); let variants = array_to_tokenstream(particle);
for (id, particle) in particle.iter().enumerate() {
let id = id as u8;
let name = ident(particle.to_pascal_case());
variants.extend([quote! {
#name = #id,
}]);
}
quote! { quote! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)] #[repr(u8)]

View File

@ -1,24 +1,15 @@
use heck::ToPascalCase;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use crate::ident; use crate::array_to_tokenstream;
pub(crate) fn build() -> TokenStream { pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=assets/screens.json"); println!("cargo:rerun-if-changed=assets/screens.json");
let screens: Vec<String> = serde_json::from_str(include_str!("../../assets/screens.json")) let screens: Vec<String> = serde_json::from_str(include_str!("../../assets/screens.json"))
.expect("Failed to parse screens.json"); .expect("Failed to parse screens.json");
let mut variants = TokenStream::new(); let variants = array_to_tokenstream(screens);
for (id, screen) in screens.iter().enumerate() {
let id = id as u8;
let name = ident(screen.to_pascal_case());
variants.extend([quote! {
#name = #id,
}]);
}
quote! { quote! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)] #[repr(u8)]

View File

@ -1,24 +1,15 @@
use heck::ToPascalCase;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use crate::ident; use crate::array_to_tokenstream;
pub(crate) fn build() -> TokenStream { pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=assets/sounds.json"); println!("cargo:rerun-if-changed=assets/sounds.json");
let sound: Vec<String> = serde_json::from_str(include_str!("../../assets/sounds.json")) let sound: Vec<String> = serde_json::from_str(include_str!("../../assets/sounds.json"))
.expect("Failed to parse sounds.json"); .expect("Failed to parse sounds.json");
let mut variants = TokenStream::new(); let variants = array_to_tokenstream(sound);
for (id, sound) in sound.iter().enumerate() {
let id = id as u16;
let name = ident(sound.to_pascal_case());
variants.extend([quote! {
#name = #id,
}]);
}
quote! { quote! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u16)] #[repr(u16)]

View File

@ -0,0 +1,20 @@
use proc_macro2::TokenStream;
use quote::quote;
use crate::array_to_tokenstream;
pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=assets/sound_category.json");
let sound_categories: Vec<String> =
serde_json::from_str(include_str!("../../assets/sound_category.json"))
.expect("Failed to parse sound_category.json");
let variants = array_to_tokenstream(sound_categories);
quote! {
#[repr(u8)]
pub enum SoundCategory {
#variants
}
}
}

View File

@ -21,3 +21,7 @@ pub mod chunk_status {
pub mod game_event { pub mod game_event {
include!(concat!(env!("OUT_DIR"), "/game_event.rs")); include!(concat!(env!("OUT_DIR"), "/game_event.rs"));
} }
pub mod sound_category {
include!(concat!(env!("OUT_DIR"), "/sound_category.rs"));
}

View File

@ -1,8 +1,8 @@
use bytes::BufMut; use bytes::BufMut;
use pumpkin_data::packet::clientbound::PLAY_SOUND_ENTITY; use pumpkin_data::{packet::clientbound::PLAY_SOUND_ENTITY, sound_category::SoundCategory};
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt}; use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundEvent, VarInt};
#[client_packet(PLAY_SOUND_ENTITY)] #[client_packet(PLAY_SOUND_ENTITY)]
pub struct CEntitySoundEffect { pub struct CEntitySoundEffect {

View File

@ -1,8 +1,8 @@
use bytes::BufMut; use bytes::BufMut;
use pumpkin_data::packet::clientbound::PLAY_SOUND; use pumpkin_data::{packet::clientbound::PLAY_SOUND, sound_category::SoundCategory};
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt}; use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundEvent, VarInt};
#[client_packet(PLAY_SOUND)] #[client_packet(PLAY_SOUND)]
pub struct CSoundEffect { pub struct CSoundEffect {

View File

@ -65,19 +65,6 @@ impl TryFrom<VarInt> for ConnectionState {
} }
} }
pub enum SoundCategory {
Master,
Music,
Records,
Weather,
Blocks,
Hostile,
Neutral,
Players,
Ambient,
Voice,
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct IDOrSoundEvent { pub struct IDOrSoundEvent {
pub id: VarInt, pub id: VarInt,

View File

@ -9,7 +9,7 @@ use std::{
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG}; use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG};
use pumpkin_data::sound::Sound; use pumpkin_data::{sound::Sound, sound_category::SoundCategory};
use pumpkin_entity::{entity_type::EntityType, EntityId}; use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_inventory::player::PlayerInventory; use pumpkin_inventory::player::PlayerInventory;
use pumpkin_protocol::server::play::{ use pumpkin_protocol::server::play::{
@ -29,7 +29,7 @@ use pumpkin_protocol::{
SPlayerRotation, SSetCreativeSlot, SSetHeldItem, SSetPlayerGround, SSwingArm, SUseItem, SPlayerRotation, SSetCreativeSlot, SSetHeldItem, SSetPlayerGround, SSwingArm, SUseItem,
SUseItemOn, SUseItemOn,
}, },
RawPacket, ServerPacket, SoundCategory, RawPacket, ServerPacket,
}; };
use pumpkin_protocol::{client::play::CUpdateTime, codec::var_int::VarInt}; use pumpkin_protocol::{client::play::CUpdateTime, codec::var_int::VarInt};
use pumpkin_protocol::{ use pumpkin_protocol::{

View File

@ -1,10 +1,9 @@
use std::f32::consts::PI; use std::f32::consts::PI;
use pumpkin_data::{particle::Particle, sound::Sound}; use pumpkin_data::{particle::Particle, sound::Sound, sound_category::SoundCategory};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::{CEntityVelocity, CParticle}, client::play::{CEntityVelocity, CParticle},
codec::var_int::VarInt, codec::var_int::VarInt,
SoundCategory,
}; };
use pumpkin_util::math::vector3::Vector3; use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::item::ItemStack; use pumpkin_world::item::ItemStack;

View File

@ -11,16 +11,13 @@ use crate::{
}; };
use level_time::LevelTime; use level_time::LevelTime;
use pumpkin_config::BasicConfiguration; use pumpkin_config::BasicConfiguration;
use pumpkin_data::sound::Sound; use pumpkin_data::{sound::Sound, sound_category::SoundCategory};
use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, EntityId}; use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, EntityId};
use pumpkin_protocol::client::play::{CBlockUpdate, CRespawn, CSoundEffect, CWorldEvent};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::CLevelEvent, client::play::CLevelEvent,
codec::{identifier::Identifier, var_int::VarInt}, codec::{identifier::Identifier, var_int::VarInt},
}; };
use pumpkin_protocol::{
client::play::{CBlockUpdate, CRespawn, CSoundEffect, CWorldEvent},
SoundCategory,
};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::{ client::play::{
CChunkData, CGameEvent, CLogin, CPlayerInfoUpdate, CRemoveEntities, CRemovePlayerInfo, CChunkData, CGameEvent, CLogin, CPlayerInfoUpdate, CRemoveEntities, CRemovePlayerInfo,