Make Snowballs and Eggs work

This commit is contained in:
Alexander Medvedev 2025-02-01 21:17:37 +01:00
parent 186e846858
commit 1729f58a6f
21 changed files with 264 additions and 79 deletions

View File

@ -231,7 +231,7 @@ pub fn pumpkin_item(input: TokenStream, item: TokenStream) -> TokenStream {
let gen = quote! { let gen = quote! {
#item #item
impl #impl_generics crate::block::pumpkin_block::BlockMetadata for #name #ty_generics { impl #impl_generics crate::item::pumpkin_item::ItemMetadata for #name #ty_generics {
const NAMESPACE: &'static str = #namespace; const NAMESPACE: &'static str = #namespace;
const ID: &'static str = #id; const ID: &'static str = #id;
} }

View File

@ -22,6 +22,10 @@ pub fn get_item(name: &str) -> Option<&Item> {
ITEMS.get(&name.replace("minecraft:", "")) ITEMS.get(&name.replace("minecraft:", ""))
} }
pub fn get_name_by_id<'a>(item_id: u16) -> Option<&'a String> {
ITEMS_REGISTRY_NAME_BY_ID.get(&item_id)
}
pub fn get_item_by_id<'a>(item_id: u16) -> Option<&'a Item> { pub fn get_item_by_id<'a>(item_id: u16) -> Option<&'a Item> {
ITEMS.values().find(|&item| item.id == item_id) ITEMS.values().find(|&item| item.id == item_id)
} }

View File

@ -29,7 +29,7 @@ pub struct ChestBlock;
#[async_trait] #[async_trait]
impl PumpkinBlock for ChestBlock { impl PumpkinBlock for ChestBlock {
async fn on_use<'a>( async fn normal_use(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -40,7 +40,7 @@ impl PumpkinBlock for ChestBlock {
.await; .await;
} }
async fn on_use_with_item<'a>( async fn use_with_item(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -53,17 +53,11 @@ impl PumpkinBlock for ChestBlock {
BlockActionResult::Consume BlockActionResult::Consume
} }
async fn on_broken<'a>( async fn broken(&self, block: &Block, player: &Player, location: BlockPos, server: &Server) {
&self,
block: &Block,
player: &Player,
location: BlockPos,
server: &Server,
) {
super::standard_on_broken_with_container(block, player, location, server).await; super::standard_on_broken_with_container(block, player, location, server).await;
} }
async fn on_close<'a>( async fn close(
&self, &self,
_block: &Block, _block: &Block,
player: &Player, player: &Player,

View File

@ -14,7 +14,7 @@ pub struct CraftingTableBlock;
#[async_trait] #[async_trait]
impl PumpkinBlock for CraftingTableBlock { impl PumpkinBlock for CraftingTableBlock {
async fn on_use<'a>( async fn normal_use(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -25,7 +25,7 @@ impl PumpkinBlock for CraftingTableBlock {
.await; .await;
} }
async fn on_use_with_item<'a>( async fn use_with_item(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -38,17 +38,11 @@ impl PumpkinBlock for CraftingTableBlock {
BlockActionResult::Consume BlockActionResult::Consume
} }
async fn on_broken<'a>( async fn broken(&self, block: &Block, player: &Player, location: BlockPos, server: &Server) {
&self,
block: &Block,
player: &Player,
location: BlockPos,
server: &Server,
) {
super::standard_on_broken_with_container(block, player, location, server).await; super::standard_on_broken_with_container(block, player, location, server).await;
} }
async fn on_close<'a>( async fn close(
&self, &self,
_block: &Block, _block: &Block,
player: &Player, player: &Player,

View File

@ -15,7 +15,7 @@ pub struct FurnaceBlock;
#[async_trait] #[async_trait]
impl PumpkinBlock for FurnaceBlock { impl PumpkinBlock for FurnaceBlock {
async fn on_use<'a>( async fn normal_use(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -26,7 +26,7 @@ impl PumpkinBlock for FurnaceBlock {
.await; .await;
} }
async fn on_use_with_item<'a>( async fn use_with_item(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -39,13 +39,7 @@ impl PumpkinBlock for FurnaceBlock {
BlockActionResult::Consume BlockActionResult::Consume
} }
async fn on_broken<'a>( async fn broken(&self, block: &Block, player: &Player, location: BlockPos, server: &Server) {
&self,
block: &Block,
player: &Player,
location: BlockPos,
server: &Server,
) {
super::standard_on_broken_with_container(block, player, location, server).await; super::standard_on_broken_with_container(block, player, location, server).await;
} }
} }

View File

@ -14,7 +14,7 @@ pub struct JukeboxBlock;
#[async_trait] #[async_trait]
impl PumpkinBlock for JukeboxBlock { impl PumpkinBlock for JukeboxBlock {
async fn on_use<'a>( async fn normal_use(
&self, &self,
_block: &Block, _block: &Block,
player: &Player, player: &Player,
@ -27,7 +27,7 @@ impl PumpkinBlock for JukeboxBlock {
world.stop_record(location).await; world.stop_record(location).await;
} }
async fn on_use_with_item<'a>( async fn use_with_item(
&self, &self,
_block: &Block, _block: &Block,
player: &Player, player: &Player,
@ -57,13 +57,7 @@ impl PumpkinBlock for JukeboxBlock {
BlockActionResult::Consume BlockActionResult::Consume
} }
async fn on_broken<'a>( async fn broken(&self, _block: &Block, player: &Player, location: BlockPos, _server: &Server) {
&self,
_block: &Block,
player: &Player,
location: BlockPos,
_server: &Server,
) {
// For now just stop the music at this position // For now just stop the music at this position
let world = &player.living_entity.entity.world; let world = &player.living_entity.entity.world;

View File

@ -17,7 +17,7 @@ pub trait BlockMetadata {
#[async_trait] #[async_trait]
pub trait PumpkinBlock: Send + Sync { pub trait PumpkinBlock: Send + Sync {
async fn on_use<'a>( async fn normal_use(
&self, &self,
_block: &Block, _block: &Block,
_player: &Player, _player: &Player,
@ -25,7 +25,7 @@ pub trait PumpkinBlock: Send + Sync {
_server: &Server, _server: &Server,
) { ) {
} }
async fn on_use_with_item<'a>( async fn use_with_item(
&self, &self,
_block: &Block, _block: &Block,
_player: &Player, _player: &Player,
@ -36,7 +36,7 @@ pub trait PumpkinBlock: Send + Sync {
BlockActionResult::Continue BlockActionResult::Continue
} }
async fn on_placed<'a>( async fn placed(
&self, &self,
_block: &Block, _block: &Block,
_player: &Player, _player: &Player,
@ -45,7 +45,7 @@ pub trait PumpkinBlock: Send + Sync {
) { ) {
} }
async fn on_broken<'a>( async fn broken(
&self, &self,
_block: &Block, _block: &Block,
_player: &Player, _player: &Player,
@ -54,7 +54,7 @@ pub trait PumpkinBlock: Send + Sync {
) { ) {
} }
async fn on_close<'a>( async fn close(
&self, &self,
_block: &Block, _block: &Block,
_player: &Player, _player: &Player,

View File

@ -34,11 +34,13 @@ impl BlockRegistry {
) { ) {
let pumpkin_block = self.get_pumpkin_block(block); let pumpkin_block = self.get_pumpkin_block(block);
if let Some(pumpkin_block) = pumpkin_block { if let Some(pumpkin_block) = pumpkin_block {
pumpkin_block.on_use(block, player, location, server).await; pumpkin_block
.normal_use(block, player, location, server)
.await;
} }
} }
pub async fn on_use_with_item( pub async fn use_with_item(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -49,7 +51,7 @@ impl BlockRegistry {
let pumpkin_block = self.get_pumpkin_block(block); let pumpkin_block = self.get_pumpkin_block(block);
if let Some(pumpkin_block) = pumpkin_block { if let Some(pumpkin_block) = pumpkin_block {
return pumpkin_block return pumpkin_block
.on_use_with_item(block, player, location, item, server) .use_with_item(block, player, location, item, server)
.await; .await;
} }
BlockActionResult::Continue BlockActionResult::Continue
@ -64,13 +66,11 @@ impl BlockRegistry {
) { ) {
let pumpkin_block = self.get_pumpkin_block(block); let pumpkin_block = self.get_pumpkin_block(block);
if let Some(pumpkin_block) = pumpkin_block { if let Some(pumpkin_block) = pumpkin_block {
pumpkin_block pumpkin_block.placed(block, player, location, server).await;
.on_placed(block, player, location, server)
.await;
} }
} }
pub async fn on_broken( pub async fn broken(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -79,13 +79,11 @@ impl BlockRegistry {
) { ) {
let pumpkin_block = self.get_pumpkin_block(block); let pumpkin_block = self.get_pumpkin_block(block);
if let Some(pumpkin_block) = pumpkin_block { if let Some(pumpkin_block) = pumpkin_block {
pumpkin_block pumpkin_block.broken(block, player, location, server).await;
.on_broken(block, player, location, server)
.await;
} }
} }
pub async fn on_close( pub async fn close(
&self, &self,
block: &Block, block: &Block,
player: &Player, player: &Player,
@ -96,7 +94,7 @@ impl BlockRegistry {
let pumpkin_block = self.get_pumpkin_block(block); let pumpkin_block = self.get_pumpkin_block(block);
if let Some(pumpkin_block) = pumpkin_block { if let Some(pumpkin_block) = pumpkin_block {
pumpkin_block pumpkin_block
.on_close(block, player, location, server, container) .close(block, player, location, server, container)
.await; .await;
} }
} }

View File

@ -235,7 +235,7 @@ impl Entity {
pub fn set_rotation(&self, yaw: f32, pitch: f32) { pub fn set_rotation(&self, yaw: f32, pitch: f32) {
// TODO // TODO
self.yaw.store(yaw); self.yaw.store(yaw);
self.pitch.store(pitch); self.pitch.store(pitch.clamp(-90.0, 90.0) % 360.0);
} }
/// Removes the Entity from their current World /// Removes the Entity from their current World

View File

@ -484,6 +484,10 @@ impl Player {
&self.living_entity.entity.world &self.living_entity.entity.world
} }
pub fn position(&self) -> Vector3<f64> {
self.living_entity.entity.pos.load()
}
/// Updates the current abilities the Player has /// Updates the current abilities the Player has
pub async fn send_abilities_update(&self) { pub async fn send_abilities_update(&self) {
let mut b = 0i8; let mut b = 0i8;
@ -984,7 +988,10 @@ impl Player {
self.handle_use_item_on(SUseItemOn::read(bytebuf)?, server) self.handle_use_item_on(SUseItemOn::read(bytebuf)?, server)
.await?; .await?;
} }
SUseItem::PACKET_ID => self.handle_use_item(&SUseItem::read(bytebuf)?), SUseItem::PACKET_ID => {
self.handle_use_item(&SUseItem::read(bytebuf)?, server)
.await;
}
SCommandSuggestion::PACKET_ID => { SCommandSuggestion::PACKET_ID => {
self.handle_command_suggestion(SCommandSuggestion::read(bytebuf)?, server) self.handle_command_suggestion(SCommandSuggestion::read(bytebuf)?, server)
.await; .await;

View File

@ -2,15 +2,21 @@ use std::f32::{self, consts::PI};
use pumpkin_util::math::vector3::Vector3; use pumpkin_util::math::vector3::Vector3;
use super::Entity; use super::{living::LivingEntity, Entity, EntityBase};
pub struct ProjectileEntity { pub struct ThrownItem {
entity: Entity, entity: Entity,
} }
const DEG_PER_RAD_F32: f32 = 180.0 / PI; const DEG_PER_RAD_F32: f32 = 180.0 / PI;
impl ProjectileEntity { impl ThrownItem {
pub fn new(entity: Entity, owner: &Entity) -> Self {
let mut owner_pos = owner.pos.load();
owner_pos.y = (owner_pos.y + f64::from(owner.standing_eye_height)) - 0.1;
entity.pos.store(owner_pos);
Self { entity }
}
pub fn set_velocity_from( pub fn set_velocity_from(
&self, &self,
shooter: &Entity, shooter: &Entity,
@ -20,9 +26,15 @@ impl ProjectileEntity {
speed: f32, speed: f32,
divergence: f32, divergence: f32,
) { ) {
let x = -(yaw * PI / 180.0).sin() * (pitch * PI / 180.0).cos(); let to_radians = |degrees: f32| degrees * PI / 180.0;
let y = -((pitch + roll) * PI / 180.0).sin();
let z = -(yaw * PI / 180.0).cos() * (pitch * PI / 180.0).cos(); let yaw_rad = to_radians(yaw);
let pitch_rad = to_radians(pitch);
let roll_rad = to_radians(pitch + roll);
let x = -yaw_rad.sin() * pitch_rad.cos();
let y = -roll_rad.sin();
let z = yaw_rad.cos() * pitch_rad.cos();
self.set_velocity( self.set_velocity(
f64::from(x), f64::from(x),
f64::from(y), f64::from(y),
@ -64,3 +76,13 @@ impl ProjectileEntity {
); );
} }
} }
impl EntityBase for ThrownItem {
fn get_entity(&self) -> &Entity {
&self.entity
}
fn get_living_entity(&self) -> Option<&LivingEntity> {
None
}
}

View File

@ -0,0 +1,37 @@
use std::sync::Arc;
use crate::entity::player::Player;
use crate::entity::projectile::ThrownItem;
use crate::item::pumpkin_item::PumpkinItem;
use crate::server::Server;
use async_trait::async_trait;
use pumpkin_data::entity::EntityType;
use pumpkin_data::sound::Sound;
use pumpkin_macros::pumpkin_item;
use pumpkin_world::item::registry::Item;
#[pumpkin_item("minecraft:egg")]
pub struct EggItem;
const POWER: f32 = 1.5;
#[async_trait]
impl PumpkinItem for EggItem {
async fn normal_use(&self, _block: &Item, player: &Player, server: &Server) {
let position = player.position();
let world = player.world();
world
.play_sound(
Sound::EntityEggThrow,
pumpkin_data::sound::SoundCategory::Players,
&position,
)
.await;
// TODO: Implement eggs the right way, so there is a chance of spawning chickens
let entity = server.add_entity(position, EntityType::Egg, world);
let snowball = ThrownItem::new(entity, &player.living_entity.entity);
let yaw = player.living_entity.entity.yaw.load();
let pitch = player.living_entity.entity.pitch.load();
snowball.set_velocity_from(&player.living_entity.entity, pitch, yaw, 0.0, POWER, 1.0);
world.spawn_entity(Arc::new(snowball)).await;
}
}

View File

@ -0,0 +1,2 @@
pub mod egg;
pub mod snowball;

View File

@ -0,0 +1,36 @@
use std::sync::Arc;
use crate::entity::player::Player;
use crate::entity::projectile::ThrownItem;
use crate::item::pumpkin_item::PumpkinItem;
use crate::server::Server;
use async_trait::async_trait;
use pumpkin_data::entity::EntityType;
use pumpkin_data::sound::Sound;
use pumpkin_macros::pumpkin_item;
use pumpkin_world::item::registry::Item;
#[pumpkin_item("minecraft:snowball")]
pub struct SnowBallItem;
const POWER: f32 = 1.5;
#[async_trait]
impl PumpkinItem for SnowBallItem {
async fn normal_use(&self, _block: &Item, player: &Player, server: &Server) {
let position = player.position();
let world = player.world();
world
.play_sound(
Sound::EntitySnowballThrow,
pumpkin_data::sound::SoundCategory::Neutral,
&position,
)
.await;
let entity = server.add_entity(position, EntityType::Snowball, world);
let snowball = ThrownItem::new(entity, &player.living_entity.entity);
let yaw = player.living_entity.entity.yaw.load();
let pitch = player.living_entity.entity.pitch.load();
snowball.set_velocity_from(&player.living_entity.entity, pitch, yaw, 0.0, POWER, 1.0);
world.spawn_entity(Arc::new(snowball)).await;
}
}

18
pumpkin/src/item/mod.rs Normal file
View File

@ -0,0 +1,18 @@
use items::{egg::EggItem, snowball::SnowBallItem};
use registry::ItemRegistry;
use std::sync::Arc;
mod items;
pub mod pumpkin_item;
pub mod registry;
#[must_use]
pub fn default_registry() -> Arc<ItemRegistry> {
let mut manager = ItemRegistry::default();
manager.register(SnowBallItem);
manager.register(EggItem);
Arc::new(manager)
}

View File

@ -0,0 +1,28 @@
use crate::entity::player::Player;
use crate::server::Server;
use async_trait::async_trait;
use pumpkin_util::math::position::BlockPos;
use pumpkin_world::block::registry::Block;
use pumpkin_world::item::registry::Item;
pub trait ItemMetadata {
const NAMESPACE: &'static str;
const ID: &'static str;
fn name(&self) -> String {
format!("{}:{}", Self::NAMESPACE, Self::ID)
}
}
#[async_trait]
pub trait PumpkinItem: Send + Sync {
async fn normal_use(&self, _block: &Item, _player: &Player, _server: &Server) {}
async fn use_on_block(
&self,
_item: &Item,
_player: &Player,
_location: BlockPos,
_block: &Block,
_server: &Server,
) {
}
}

View File

@ -0,0 +1,49 @@
use crate::entity::player::Player;
use crate::server::Server;
use pumpkin_util::math::position::BlockPos;
use pumpkin_world::block::registry::Block;
use pumpkin_world::item::registry::Item;
use std::collections::HashMap;
use std::sync::Arc;
use super::pumpkin_item::{ItemMetadata, PumpkinItem};
#[derive(Default)]
pub struct ItemRegistry {
blocks: HashMap<String, Arc<dyn PumpkinItem>>,
}
impl ItemRegistry {
pub fn register<T: PumpkinItem + ItemMetadata + 'static>(&mut self, block: T) {
self.blocks.insert(block.name(), Arc::new(block));
}
pub async fn on_use(&self, item_name: &str, item: &Item, player: &Player, server: &Server) {
let pumpkin_block = self.get_pumpkin_item(item_name);
if let Some(pumpkin_block) = pumpkin_block {
pumpkin_block.normal_use(item, player, server).await;
}
}
pub async fn use_on_block(
&self,
item_name: &str,
item: &Item,
player: &Player,
location: BlockPos,
block: &Block,
server: &Server,
) {
let pumpkin_block = self.get_pumpkin_item(item_name);
if let Some(pumpkin_block) = pumpkin_block {
return pumpkin_block
.use_on_block(item, player, location, block, server)
.await;
}
}
#[must_use]
pub fn get_pumpkin_item(&self, item_name: &str) -> Option<&Arc<dyn PumpkinItem>> {
self.blocks.get(format!("minecraft:{item_name}").as_str())
}
}

View File

@ -24,6 +24,7 @@ pub mod command;
pub mod data; pub mod data;
pub mod entity; pub mod entity;
pub mod error; pub mod error;
pub mod item;
pub mod net; pub mod net;
pub mod plugin; pub mod plugin;
pub mod server; pub mod server;

View File

@ -58,6 +58,7 @@ pub mod command;
pub mod data; pub mod data;
pub mod entity; pub mod entity;
pub mod error; pub mod error;
pub mod item;
pub mod net; pub mod net;
pub mod plugin; pub mod plugin;
pub mod server; pub mod server;

View File

@ -45,7 +45,7 @@ use pumpkin_util::{
}; };
use pumpkin_world::block::registry::get_block_collision_shapes; use pumpkin_world::block::registry::get_block_collision_shapes;
use pumpkin_world::block::registry::Block; use pumpkin_world::block::registry::Block;
use pumpkin_world::item::registry::get_item_by_id; use pumpkin_world::item::registry::{get_item_by_id, get_name_by_id};
use pumpkin_world::item::ItemStack; use pumpkin_world::item::ItemStack;
use pumpkin_world::{ use pumpkin_world::{
block::{registry::get_block_by_item, BlockDirection}, block::{registry::get_block_by_item, BlockDirection},
@ -236,10 +236,7 @@ impl Player {
.on_ground .on_ground
.store(packet.ground, std::sync::atomic::Ordering::Relaxed); .store(packet.ground, std::sync::atomic::Ordering::Relaxed);
entity.set_rotation( entity.set_rotation(wrap_degrees(packet.yaw) % 360.0, wrap_degrees(packet.pitch));
wrap_degrees(packet.yaw) % 360.0,
wrap_degrees(packet.pitch).clamp(-90.0, 90.0) % 360.0,
);
let entity_id = entity.entity_id; let entity_id = entity.entity_id;
let Vector3 { x, y, z } = position; let Vector3 { x, y, z } = position;
@ -316,7 +313,7 @@ impl Player {
.store(rotation.ground, std::sync::atomic::Ordering::Relaxed); .store(rotation.ground, std::sync::atomic::Ordering::Relaxed);
entity.set_rotation( entity.set_rotation(
wrap_degrees(rotation.yaw) % 360.0, wrap_degrees(rotation.yaw) % 360.0,
wrap_degrees(rotation.pitch).clamp(-90.0, 90.0) % 360.0, wrap_degrees(rotation.pitch),
); );
// send new position to all other players // send new position to all other players
let entity_id = entity.entity_id; let entity_id = entity.entity_id;
@ -799,7 +796,7 @@ impl Player {
if let Ok(block) = block { if let Ok(block) = block {
server server
.block_registry .block_registry
.on_broken(block, &self, location, server) .broken(block, &self, location, server)
.await; .await;
} }
} }
@ -837,7 +834,7 @@ impl Player {
if let Ok(block) = block { if let Ok(block) = block {
server server
.block_registry .block_registry
.on_broken(block, &self, location, server) .broken(block, &self, location, server)
.await; .await;
} }
} }
@ -950,7 +947,7 @@ impl Player {
{ {
let action_result = server let action_result = server
.block_registry .block_registry
.on_use_with_item(block, self, location, item, server) .use_with_item(block, self, location, item, server)
.await; .await;
match action_result { match action_result {
BlockActionResult::Continue => {} BlockActionResult::Continue => {}
@ -995,12 +992,17 @@ impl Player {
Ok(()) Ok(())
} }
pub fn handle_use_item(&self, _use_item: &SUseItem) { pub async fn handle_use_item(&self, _use_item: &SUseItem, server: &Server) {
if !self.has_client_loaded() { if !self.has_client_loaded() {
return; return;
} }
// TODO: handle packet correctly if let Some(held) = self.inventory().lock().await.held_item() {
log::error!("An item was used(SUseItem), but the packet is not implemented yet"); // this is so ugly and slow brooo...
if let Some(item) = get_item_by_id(held.item_id) {
let name = get_name_by_id(item.id).unwrap();
server.item_registry.on_use(name, item, self, server).await;
}
}
} }
pub async fn handle_set_held_item(&self, held: SSetHeldItem) { pub async fn handle_set_held_item(&self, held: SSetHeldItem) {
@ -1054,7 +1056,7 @@ impl Player {
if let Some(block) = container.get_block() { if let Some(block) = container.get_block() {
server server
.block_registry .block_registry
.on_close(&block, self, pos, server, container) //block, self, location, server) .close(&block, self, pos, server, container) //block, self, location, server)
.await; .await;
} }
} }

View File

@ -30,10 +30,11 @@ use std::{
}; };
use tokio::sync::{Mutex, RwLock}; use tokio::sync::{Mutex, RwLock};
use crate::block::default_block_properties_manager;
use crate::block::properties::BlockPropertiesManager; use crate::block::properties::BlockPropertiesManager;
use crate::block::registry::BlockRegistry; use crate::block::registry::BlockRegistry;
use crate::block::{self, default_block_properties_manager};
use crate::entity::{Entity, EntityId}; use crate::entity::{Entity, EntityId};
use crate::item::registry::ItemRegistry;
use crate::net::EncryptionError; use crate::net::EncryptionError;
use crate::world::custom_bossbar::CustomBossbars; use crate::world::custom_bossbar::CustomBossbars;
use crate::{ use crate::{
@ -61,6 +62,8 @@ pub struct Server {
pub command_dispatcher: RwLock<CommandDispatcher>, pub command_dispatcher: RwLock<CommandDispatcher>,
/// Block Behaviour /// Block Behaviour
pub block_registry: Arc<BlockRegistry>, pub block_registry: Arc<BlockRegistry>,
/// Item Behaviour
pub item_registry: Arc<ItemRegistry>,
/// Creates and stores block property registry and managed behaviours. /// Creates and stores block property registry and managed behaviours.
pub block_properties_manager: Arc<BlockPropertiesManager>, pub block_properties_manager: Arc<BlockPropertiesManager>,
/// Manages multiple worlds within the server. /// Manages multiple worlds within the server.
@ -132,7 +135,8 @@ impl Server {
DimensionType::TheEnd, DimensionType::TheEnd,
], ],
command_dispatcher, command_dispatcher,
block_registry: block::default_registry(), block_registry: super::block::default_registry(),
item_registry: super::item::default_registry(),
block_properties_manager: default_block_properties_manager(), block_properties_manager: default_block_properties_manager(),
auth_client, auth_client,
key_store: KeyStore::new(), key_store: KeyStore::new(),