parse world events at compile time

This commit is contained in:
Alexander Medvedev 2025-01-11 17:06:21 +01:00
parent 03cb80b216
commit 308c125a20
5 changed files with 43 additions and 2 deletions

1
assets/world_event.json Normal file
View File

@ -0,0 +1 @@
{"DISPENSER_DISPENSES":1000,"DISPENSER_FAILS":1001,"DISPENSER_LAUNCHES_PROJECTILE":1002,"FIREWORK_ROCKET_SHOOTS":1004,"FIRE_EXTINGUISHED":1009,"JUKEBOX_STARTS_PLAYING":1010,"JUKEBOX_STOPS_PLAYING":1011,"GHAST_WARNS":1015,"GHAST_SHOOTS":1016,"ENDER_DRAGON_SHOOTS":1017,"BLAZE_SHOOTS":1018,"ZOMBIE_ATTACKS_WOODEN_DOOR":1019,"ZOMBIE_ATTACKS_IRON_DOOR":1020,"ZOMBIE_BREAKS_WOODEN_DOOR":1021,"WITHER_BREAKS_BLOCK":1022,"WITHER_SPAWNS":1023,"WITHER_SHOOTS":1024,"BAT_TAKES_OFF":1025,"ZOMBIE_INFECTS_VILLAGER":1026,"ZOMBIE_VILLAGER_CURED":1027,"ENDER_DRAGON_DIES":1028,"ANVIL_DESTROYED":1029,"ANVIL_USED":1030,"ANVIL_LANDS":1031,"TRAVEL_THROUGH_PORTAL":1032,"CHORUS_FLOWER_GROWS":1033,"CHORUS_FLOWER_DIES":1034,"BREWING_STAND_BREWS":1035,"END_PORTAL_OPENED":1038,"PHANTOM_BITES":1039,"ZOMBIE_CONVERTS_TO_DROWNED":1040,"HUSK_CONVERTS_TO_ZOMBIE":1041,"GRINDSTONE_USED":1042,"LECTERN_BOOK_PAGE_TURNED":1043,"SMITHING_TABLE_USED":1044,"POINTED_DRIPSTONE_LANDS":1045,"POINTED_DRIPSTONE_DRIPS_LAVA_INTO_CAULDRON":1046,"POINTED_DRIPSTONE_DRIPS_WATER_INTO_CAULDRON":1047,"SKELETON_CONVERTS_TO_STRAY":1048,"CRAFTER_CRAFTS":1049,"CRAFTER_FAILS":1050,"field_51787":1051,"COMPOSTER_USED":1500,"LAVA_EXTINGUISHED":1501,"REDSTONE_TORCH_BURNS_OUT":1502,"END_PORTAL_FRAME_FILLED":1503,"POINTED_DRIPSTONE_DRIPS":1504,"BONE_MEAL_USED":1505,"DISPENSER_ACTIVATED":2000,"BLOCK_BROKEN":2001,"SPLASH_POTION_SPLASHED":2002,"EYE_OF_ENDER_BREAKS":2003,"SPAWNER_SPAWNS_MOB":2004,"DRAGON_BREATH_CLOUD_SPAWNS":2006,"INSTANT_SPLASH_POTION_SPLASHED":2007,"ENDER_DRAGON_BREAKS_BLOCK":2008,"WET_SPONGE_DRIES_OUT":2009,"CRAFTER_SHOOTS":2010,"BEE_FERTILIZES_PLANT":2011,"TURTLE_EGG_PLACED":2012,"SMASH_ATTACK":2013,"END_GATEWAY_SPAWNS":3000,"ENDER_DRAGON_RESURRECTED":3001,"ELECTRICITY_SPARKS":3002,"BLOCK_WAXED":3003,"WAX_REMOVED":3004,"BLOCK_SCRAPED":3005,"SCULK_CHARGE":3006,"SCULK_SHRIEKS":3007,"BLOCK_FINISHED_BRUSHING":3008,"SNIFFER_EGG_CRACKS":3009,"TRIAL_SPAWNER_SPAWNS_MOB":3011,"TRIAL_SPAWNER_SPAWNS_MOB_AT_SPAWN_POS":3012,"TRIAL_SPAWNER_DETECTS_PLAYER":3013,"TRIAL_SPAWNER_EJECTS_ITEM":3014,"VAULT_ACTIVATES":3015,"VAULT_DEACTIVATES":3016,"VAULT_EJECTS_ITEM":3017,"COBWEB_WEAVED":3018,"OMINOUS_TRIAL_SPAWNER_DETECTS_PLAYER":3019,"TRIAL_SPAWNER_TURNS_OMINOUS":3020,"OMINOUS_ITEM_SPAWNER_SPAWNS_ITEM":3021}

View File

@ -14,6 +14,7 @@ mod scoreboard_slot;
mod screen; mod screen;
mod sound; mod sound;
mod sound_category; mod sound_category;
mod world_event;
pub fn main() { pub fn main() {
write_generated_file(packet::build(), "packet.rs"); write_generated_file(packet::build(), "packet.rs");
@ -25,6 +26,7 @@ pub fn main() {
write_generated_file(sound_category::build(), "sound_category.rs"); write_generated_file(sound_category::build(), "sound_category.rs");
write_generated_file(entity_pose::build(), "entity_pose.rs"); write_generated_file(entity_pose::build(), "entity_pose.rs");
write_generated_file(scoreboard_slot::build(), "scoreboard_slot.rs"); write_generated_file(scoreboard_slot::build(), "scoreboard_slot.rs");
write_generated_file(world_event::build(), "world_event.rs");
} }
pub fn array_to_tokenstream(array: Vec<String>) -> TokenStream { pub fn array_to_tokenstream(array: Vec<String>) -> TokenStream {

View File

@ -0,0 +1,29 @@
use std::collections::HashMap;
use heck::ToPascalCase;
use proc_macro2::TokenStream;
use quote::quote;
use crate::ident;
pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=assets/world_event.json");
let events: HashMap<String, u16> =
serde_json::from_str(include_str!("../../assets/world_event.json"))
.expect("Failed to parse world_event.json");
let mut variants = TokenStream::new();
for (event, id) in events.iter() {
let name = ident(event.to_pascal_case());
variants.extend([quote! {
#name = #id,
}]);
}
quote! {
#[repr(u16)]
pub enum WorldEvent {
#variants
}
}
}

View File

@ -27,6 +27,10 @@ pub mod entity {
include!(concat!(env!("OUT_DIR"), "/entity_pose.rs")); include!(concat!(env!("OUT_DIR"), "/entity_pose.rs"));
} }
pub mod world {
include!(concat!(env!("OUT_DIR"), "/world_event.rs"));
}
pub mod scoreboard { pub mod scoreboard {
include!(concat!(env!("OUT_DIR"), "/scoreboard_slot.rs")); include!(concat!(env!("OUT_DIR"), "/scoreboard_slot.rs"));
} }

View File

@ -14,6 +14,7 @@ use pumpkin_config::BasicConfiguration;
use pumpkin_data::{ use pumpkin_data::{
entity::EntityPose, entity::EntityPose,
sound::{Sound, SoundCategory}, sound::{Sound, SoundCategory},
world::WorldEvent,
}; };
use pumpkin_entity::{entity_type::EntityType, EntityId}; use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_protocol::client::play::{CBlockUpdate, CRespawn, CSoundEffect, CWorldEvent}; use pumpkin_protocol::client::play::{CBlockUpdate, CRespawn, CSoundEffect, CWorldEvent};
@ -886,8 +887,12 @@ impl World {
pub async fn break_block(&self, position: WorldPosition, cause: Option<&Player>) { pub async fn break_block(&self, position: WorldPosition, cause: Option<&Player>) {
let broken_block_state_id = self.set_block_state(position, 0).await; let broken_block_state_id = self.set_block_state(position, 0).await;
let particles_packet = let particles_packet = CWorldEvent::new(
CWorldEvent::new(2001, &position, broken_block_state_id.into(), false); WorldEvent::BlockBroken as i32,
&position,
broken_block_state_id.into(),
false,
);
match cause { match cause {
Some(player) => { Some(player) => {