parse entity types at compile time

This commit is contained in:
Alexander Medvedev
2025-01-11 17:59:36 +01:00
parent 308c125a20
commit aad1f91acb
18 changed files with 88 additions and 185 deletions

View File

@@ -3,7 +3,6 @@ resolver = "2"
members = [
"pumpkin-config",
"pumpkin-util",
"pumpkin-entity",
"pumpkin-inventory",
"pumpkin-macros/",
"pumpkin-protocol/",

File diff suppressed because one or more lines are too long

View File

@@ -7,6 +7,7 @@ use syn::Ident;
mod chunk_status;
mod entity_pose;
mod entity_type;
mod game_event;
mod packet;
mod particle;
@@ -27,6 +28,7 @@ pub fn main() {
write_generated_file(entity_pose::build(), "entity_pose.rs");
write_generated_file(scoreboard_slot::build(), "scoreboard_slot.rs");
write_generated_file(world_event::build(), "world_event.rs");
write_generated_file(entity_type::build(), "entity_type.rs");
}
pub fn array_to_tokenstream(array: Vec<String>) -> TokenStream {

View File

@@ -0,0 +1,59 @@
use std::collections::HashMap;
use heck::ToPascalCase;
use proc_macro2::TokenStream;
use quote::quote;
use serde::Deserialize;
use crate::ident;
#[derive(Deserialize)]
pub struct JSONStruct {
id: u16,
}
pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=assets/entities.json");
let json: HashMap<String, JSONStruct> =
serde_json::from_str(include_str!("../../assets/entities.json"))
.expect("Failed to parse sound_category.json");
let mut variants = TokenStream::new();
for (item, id) in json.iter() {
let id = id.id as u8;
let name = ident(item.to_pascal_case());
variants.extend([quote! {
#name = #id,
}]);
}
let type_from_raw_id_arms = json
.iter()
.map(|sound| {
let id = &sound.1.id;
let name = ident(sound.0.to_pascal_case());
quote! {
#id => Some(Self::#name),
}
})
.collect::<TokenStream>();
quote! {
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum EntityType {
#variants
}
impl EntityType {
pub const fn from_raw(id: u16) -> Option<Self> {
match id {
#type_from_raw_id_arms
_ => None
}
}
}
}
}

View File

@@ -24,6 +24,7 @@ pub mod game_event {
}
pub mod entity {
include!(concat!(env!("OUT_DIR"), "/entity_type.rs"));
include!(concat!(env!("OUT_DIR"), "/entity_pose.rs"));
}

View File

@@ -1,6 +0,0 @@
[package]
name = "pumpkin-entity"
version.workspace = true
edition.workspace = true
[dependencies]

View File

@@ -1,154 +0,0 @@
// TODO make this dynamic
#[derive(Clone)]
#[repr(i32)]
pub enum EntityType {
AcaciaBoat = 0,
AcaciaChestBoat = 1,
Allay = 2,
AreaEffectCloud = 3,
Armadillo = 4,
ArmorStand = 5,
Arrow = 6,
Axolotl = 7,
BambooChestRaft = 8,
BambooRaft = 9,
Bat = 10,
Bee = 11,
BirchBoat = 12,
BirchChestBoat = 13,
Blaze = 14,
BlockDisplay = 15,
Bogged = 16,
Breeze = 17,
BreezeWindCharge = 18,
Camel = 19,
Cat = 20,
CaveSpider = 21,
CherryBoat = 22,
CherryChestBoat = 23,
ChestMinecart = 24,
Chicken = 25,
Cod = 26,
CommandBlockMinecart = 27,
Cow = 28,
Creaking = 29,
Creeper = 30,
DarkOakBoat = 31,
DarkOakChestBoat = 32,
Dolphin = 33,
Donkey = 34,
DragonFireball = 35,
Drowned = 36,
Egg = 37,
ElderGuardian = 38,
Enderman = 39,
Endermite = 40,
EnderDragon = 41,
EnderPearl = 42,
EndCrystal = 43,
Evoker = 44,
EvokerFangs = 45,
ExperienceBottle = 46,
ExperienceOrb = 47,
EyeOfEnder = 48,
FallingBlock = 49,
Fireball = 50,
FireworkRocket = 51,
Fox = 52,
Frog = 53,
FurnaceMinecart = 54,
Ghast = 55,
Giant = 56,
GlowItemFrame = 57,
GlowSquid = 58,
Goat = 59,
Guardian = 60,
Hoglin = 61,
HopperMinecart = 62,
Horse = 63,
Husk = 64,
Illusioner = 65,
Interaction = 66,
IronGolem = 67,
Item = 68,
ItemDisplay = 69,
ItemFrame = 70,
JungleBoat = 71,
JungleChestBoat = 72,
LeashKnot = 73,
LightningBolt = 74,
Llama = 75,
LlamaSpit = 76,
MagmaCube = 77,
MangroveBoat = 78,
MangroveChestBoat = 79,
Marker = 80,
Minecart = 81,
Mooshroom = 82,
Mule = 83,
OakBoat = 84,
OakChestBoat = 85,
Ocelot = 86,
OminousItemSpawner = 87,
Painting = 88,
PaleOakBoat = 89,
PaleOakChestBoat = 90,
Panda = 91,
Parrot = 92,
Phantom = 93,
Pig = 94,
Piglin = 95,
PiglinBrute = 96,
Pillager = 97,
PolarBear = 98,
Potion = 99,
Pufferfish = 100,
Rabbit = 101,
Ravager = 102,
Salmon = 103,
Sheep = 104,
Shulker = 105,
ShulkerBullet = 106,
Silverfish = 107,
Skeleton = 108,
SkeletonHorse = 109,
Slime = 110,
SmallFireball = 111,
Sniffer = 112,
Snowball = 113,
SnowGolem = 114,
SpawnerMinecart = 115,
SpectralArrow = 116,
Spider = 117,
SpruceBoat = 118,
SpruceChestBoat = 119,
Squid = 120,
Stray = 121,
Strider = 122,
Tadpole = 123,
TextDisplay = 124,
Tnt = 125,
TntMinecart = 126,
TraderLlama = 127,
Trident = 128,
TropicalFish = 129,
Turtle = 130,
Vex = 131,
Villager = 132,
Vindicator = 133,
WanderingTrader = 134,
Warden = 135,
WindCharge = 136,
Witch = 137,
Wither = 138,
WitherSkeleton = 139,
WitherSkull = 140,
Wolf = 141,
Zoglin = 142,
Zombie = 143,
ZombieHorse = 144,
ZombieVillager = 145,
ZombifiedPiglin = 146,
Player = 147,
FishingBobber = 148,
}

View File

@@ -1,3 +0,0 @@
pub mod entity_type;
pub type EntityId = i32;

View File

@@ -28,7 +28,7 @@ pub fn get_entity_by_id<'a>(entity_id: u16) -> Option<&'a Entity> {
pub struct Entity {
pub id: u16,
pub max_health: Option<f32>,
pub attackable: bool,
pub attackable: Option<bool>,
pub summonable: bool,
pub fire_immune: bool,
pub dimension: [f32; 2],

View File

@@ -18,7 +18,6 @@ pumpkin-config = { path = "../pumpkin-config" }
pumpkin-inventory = { path = "../pumpkin-inventory" }
pumpkin-world = { path = "../pumpkin-world" }
pumpkin-data = { path = "../pumpkin-data" }
pumpkin-entity = { path = "../pumpkin-entity" }
pumpkin-protocol = { path = "../pumpkin-protocol" }
pumpkin-registry = { path = "../pumpkin-registry" }
pumpkin-macros = { path = "../pumpkin-macros" }

View File

@@ -1,13 +1,12 @@
use std::sync::atomic::AtomicI32;
use crossbeam::atomic::AtomicCell;
use pumpkin_entity::EntityId;
use pumpkin_inventory::{Container, EmptyContainer};
use pumpkin_protocol::client::play::{CDamageEvent, CEntityStatus, CSetEntityMetadata, Metadata};
use pumpkin_util::math::vector3::Vector3;
use tokio::sync::Mutex;
use super::Entity;
use super::{Entity, EntityId};
/// Represents a living entity within the game world.
///

View File

@@ -1,6 +1,6 @@
use std::sync::Arc;
use pumpkin_entity::entity_type::EntityType;
use pumpkin_data::entity::EntityType;
use pumpkin_util::math::vector3::Vector3;
use tokio::sync::Mutex;
use uuid::Uuid;

View File

@@ -1,6 +1,6 @@
use std::sync::Arc;
use pumpkin_entity::entity_type::EntityType;
use pumpkin_data::entity::EntityType;
use pumpkin_util::math::vector3::Vector3;
use uuid::Uuid;

View File

@@ -2,8 +2,7 @@ use core::f32;
use std::sync::{atomic::AtomicBool, Arc};
use crossbeam::atomic::AtomicCell;
use pumpkin_data::entity::EntityPose;
use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_data::entity::{EntityPose, EntityType};
use pumpkin_protocol::{
client::play::{CHeadRot, CSetEntityMetadata, CTeleportEntity, CUpdateEntityRot, Metadata},
codec::var_int::VarInt,
@@ -25,6 +24,8 @@ pub mod mob;
pub mod living;
pub mod player;
pub type EntityId = i32;
/// Represents a not living Entity (e.g. Item, Egg, Snowball...)
pub struct Entity {
/// A unique identifier for the entity

View File

@@ -9,8 +9,10 @@ use std::{
use crossbeam::atomic::AtomicCell;
use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG};
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_data::{
entity::EntityType,
sound::{Sound, SoundCategory},
};
use pumpkin_inventory::player::PlayerInventory;
use pumpkin_protocol::server::play::{
SCloseContainer, SCookieResponse as SPCookieResponse, SPlayPingRequest, SPlayerLoaded,
@@ -56,7 +58,7 @@ use pumpkin_world::{
};
use tokio::sync::{Mutex, Notify, RwLock};
use super::Entity;
use super::{Entity, EntityId};
use crate::{
command::{client_cmd_suggestions, dispatcher::CommandDispatcher},
data::op_data::OPERATOR_CONFIG,

View File

@@ -12,7 +12,7 @@ use crate::{
world::player_chunker,
};
use pumpkin_config::ADVANCED_CONFIG;
use pumpkin_entity::entity_type::EntityType;
use pumpkin_data::entity::EntityType;
use pumpkin_inventory::player::PlayerInventory;
use pumpkin_inventory::InventoryError;
use pumpkin_protocol::client::play::{CSetContainerSlot, CSetHeldItem, CSpawnEntity};
@@ -1046,7 +1046,13 @@ impl Player {
);
// TODO: this should not be hardcoded
let (mob, uuid) = mob::from_type(EntityType::Zombie, server, pos, self.world()).await;
let (mob, uuid) = mob::from_type(
EntityType::from_raw(*spawn_item_id).unwrap(),
server,
pos,
self.world(),
)
.await;
let yaw = wrap_degrees(rand::random::<f32>() * 360.0) % 360.0;
mob.living_entity.entity.set_rotation(yaw, 0.0);

View File

@@ -2,8 +2,7 @@ use connection_cache::{CachedBranding, CachedStatus};
use crossbeam::atomic::AtomicCell;
use key_store::KeyStore;
use pumpkin_config::BASIC_CONFIG;
use pumpkin_entity::entity_type::EntityType;
use pumpkin_entity::EntityId;
use pumpkin_data::entity::EntityType;
use pumpkin_inventory::drag_handler::DragHandler;
use pumpkin_inventory::{Container, OpenContainer};
use pumpkin_protocol::client::login::CEncryptionRequest;
@@ -35,7 +34,7 @@ use crate::block::default_block_manager;
use crate::entity::ai::path::Navigator;
use crate::entity::living::LivingEntity;
use crate::entity::mob::MobEntity;
use crate::entity::Entity;
use crate::entity::{Entity, EntityId};
use crate::net::EncryptionError;
use crate::world::custom_bossbar::CustomBossbars;
use crate::{
@@ -231,7 +230,7 @@ impl Server {
let entity_id = self.new_entity_id();
// TODO: this should be resolved to a integer using a macro when calling this function
let bounding_box_size = get_entity_by_id(entity_type.clone() as u16).map_or(
let bounding_box_size = get_entity_by_id(entity_type as u16).map_or(
BoundingBoxSize {
width: 0.6,
height: 1.8,

View File

@@ -5,18 +5,17 @@ pub mod player_chunker;
use crate::{
command::client_cmd_suggestions,
entity::{living::LivingEntity, mob::MobEntity, player::Player, Entity},
entity::{living::LivingEntity, mob::MobEntity, player::Player, Entity, EntityId},
error::PumpkinError,
server::Server,
};
use level_time::LevelTime;
use pumpkin_config::BasicConfiguration;
use pumpkin_data::{
entity::EntityPose,
entity::{EntityPose, EntityType},
sound::{Sound, SoundCategory},
world::WorldEvent,
};
use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_protocol::client::play::{CBlockUpdate, CRespawn, CSoundEffect, CWorldEvent};
use pumpkin_protocol::{
client::play::CLevelEvent,