Make Snowballs and Eggs work
This commit is contained in:
parent
186e846858
commit
1729f58a6f
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
37
pumpkin/src/item/items/egg.rs
Normal file
37
pumpkin/src/item/items/egg.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
pumpkin/src/item/items/mod.rs
Normal file
2
pumpkin/src/item/items/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod egg;
|
||||||
|
pub mod snowball;
|
||||||
36
pumpkin/src/item/items/snowball.rs
Normal file
36
pumpkin/src/item/items/snowball.rs
Normal 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
18
pumpkin/src/item/mod.rs
Normal 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)
|
||||||
|
}
|
||||||
28
pumpkin/src/item/pumpkin_item.rs
Normal file
28
pumpkin/src/item/pumpkin_item.rs
Normal 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,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
49
pumpkin/src/item/registry.rs
Normal file
49
pumpkin/src/item/registry.rs
Normal 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())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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(),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user