feat: building snow golem
This commit is contained in:
parent
f7b70bafb6
commit
59c82aa30e
@ -14,16 +14,36 @@ use pumpkin_util::math::vector3::Vector3;
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
/// Flags used to control the side effects of a block state change.
|
||||||
|
/// These match the internal bitmask used by Minecraft's `setBlockState` method
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct BlockFlags: u32 {
|
pub struct BlockFlags: u32 {
|
||||||
|
/// Causes a neighbor update to be sent to surrounding blocks.
|
||||||
|
/// This is what makes observers detect changes or redstone components react
|
||||||
const NOTIFY_NEIGHBORS = 0b000_0000_0001;
|
const NOTIFY_NEIGHBORS = 0b000_0000_0001;
|
||||||
|
/// Notifies listeners (like clients) that the block has changed.
|
||||||
|
/// On the server, this triggers a packet to be sent to players in range
|
||||||
const NOTIFY_LISTENERS = 0b000_0000_0010;
|
const NOTIFY_LISTENERS = 0b000_0000_0010;
|
||||||
|
/// Combines neighbor notification and listener notification.
|
||||||
|
/// This is the "standard" update used for most block placements
|
||||||
const NOTIFY_ALL = 0b000_0000_0011;
|
const NOTIFY_ALL = 0b000_0000_0011;
|
||||||
|
/// Forces the block state to be set even if it matches the current state
|
||||||
|
/// Used by items like the Debug Stick to bypass "virtual" change checks
|
||||||
const FORCE_STATE = 0b000_0000_0100;
|
const FORCE_STATE = 0b000_0000_0100;
|
||||||
|
/// Prevents the previous block from dropping items when it is replaced
|
||||||
|
/// Commonly used when a block is "transformed" rather than destroyed
|
||||||
const SKIP_DROPS = 0b000_0000_1000;
|
const SKIP_DROPS = 0b000_0000_1000;
|
||||||
|
/// Signals that the block is being moved (usually by a piston)
|
||||||
|
/// This prevents certain "on-break" logic from firing until the move is complete
|
||||||
const MOVED = 0b000_0001_0000;
|
const MOVED = 0b000_0001_0000;
|
||||||
|
/// Prevents redstone wire from re-calculating its shape/power immediately
|
||||||
|
/// Used during massive redstone updates to reduce calculation lag
|
||||||
const SKIP_REDSTONE_WIRE_STATE_REPLACEMENT = 0b000_0010_0000;
|
const SKIP_REDSTONE_WIRE_STATE_REPLACEMENT = 0b000_0010_0000;
|
||||||
|
/// If set, the `on_replaced` callback for block entities (containers) is skipped
|
||||||
|
/// Useful if you are moving a Block Entity and don't want it to drop its contents yet
|
||||||
const SKIP_BLOCK_ENTITY_REPLACED_CALLBACK = 0b000_0100_0000;
|
const SKIP_BLOCK_ENTITY_REPLACED_CALLBACK = 0b000_0100_0000;
|
||||||
|
/// Prevents the `on_added` logic from firing for the new block state
|
||||||
|
/// Use this to avoid recursive placement loops or unnecessary initialization
|
||||||
const SKIP_BLOCK_ADDED_CALLBACK = 0b000_1000_0000;
|
const SKIP_BLOCK_ADDED_CALLBACK = 0b000_1000_0000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
use pumpkin_data::{
|
use pumpkin_data::{
|
||||||
Block,
|
Block,
|
||||||
block_properties::{BlockProperties, WallTorchLikeProperties},
|
block_properties::{BlockProperties, WallTorchLikeProperties},
|
||||||
|
entity::EntityType,
|
||||||
|
world::WorldEvent,
|
||||||
};
|
};
|
||||||
use pumpkin_world::BlockStateId;
|
use pumpkin_world::{BlockStateId, world::BlockFlags};
|
||||||
|
|
||||||
use crate::block::{BlockBehaviour, BlockFuture, BlockMetadata, OnPlaceArgs};
|
use crate::{
|
||||||
|
block::{BlockBehaviour, BlockFuture, BlockMetadata, OnPlaceArgs, PlacedArgs},
|
||||||
|
entity::{Entity, passive::snow_golem::SnowGolemEntity},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct CarvedPumpkinBlock;
|
pub struct CarvedPumpkinBlock;
|
||||||
|
|
||||||
@ -31,4 +36,39 @@ impl BlockBehaviour for CarvedPumpkinBlock {
|
|||||||
props.to_state_id(args.block)
|
props.to_state_id(args.block)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||||
|
// Mojang uses some BlockPattern magic, way too complex tbh
|
||||||
|
Box::pin(async {
|
||||||
|
let down_pos = args.position.down();
|
||||||
|
let upper = args.world.get_block(&down_pos).await;
|
||||||
|
let lower = args.world.get_block(&down_pos.down()).await;
|
||||||
|
if upper == &Block::SNOW_BLOCK && lower == &Block::SNOW_BLOCK {
|
||||||
|
for i in 0..3 {
|
||||||
|
let pos = args.position.down_height(i);
|
||||||
|
args.world
|
||||||
|
.set_block_state(
|
||||||
|
&pos,
|
||||||
|
Block::AIR.default_state.id,
|
||||||
|
BlockFlags::NOTIFY_LISTENERS,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
args.world
|
||||||
|
.sync_world_event(
|
||||||
|
WorldEvent::BlockBroken,
|
||||||
|
pos,
|
||||||
|
Block::SNOW_BLOCK.default_state.id.into(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
let entity = Entity::new(
|
||||||
|
args.world.clone(),
|
||||||
|
down_pos.down().to_centered_f64(),
|
||||||
|
&EntityType::SNOW_GOLEM,
|
||||||
|
);
|
||||||
|
let golem = SnowGolemEntity::make(entity).await;
|
||||||
|
args.world.spawn_entity(golem).await;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,6 @@ use pumpkin_macros::pumpkin_block;
|
|||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_world::{BlockStateId, item::ItemStack, tick::TickPriority, world::BlockFlags};
|
use pumpkin_world::{BlockStateId, item::ItemStack, tick::TickPriority, world::BlockFlags};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
#[pumpkin_block("minecraft:composter")]
|
#[pumpkin_block("minecraft:composter")]
|
||||||
pub struct ComposterBlock;
|
pub struct ComposterBlock;
|
||||||
@ -142,13 +141,7 @@ impl ComposterBlock {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let item_entity = ItemEntity::new(
|
let item_entity = ItemEntity::new(
|
||||||
Entity::new(
|
Entity::new(world.clone(), item_position, &EntityType::ITEM),
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
item_position,
|
|
||||||
&EntityType::ITEM,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
ItemStack::new(1, &Item::BONE_MEAL),
|
ItemStack::new(1, &Item::BONE_MEAL),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ pub mod candle_cakes;
|
|||||||
pub mod candles;
|
pub mod candles;
|
||||||
pub mod carpet;
|
pub mod carpet;
|
||||||
pub mod carved_pumpkin;
|
pub mod carved_pumpkin;
|
||||||
|
pub mod wither_skull;
|
||||||
pub mod chain;
|
pub mod chain;
|
||||||
pub mod chests;
|
pub mod chests;
|
||||||
pub mod chiseled_bookshelf;
|
pub mod chiseled_bookshelf;
|
||||||
|
|||||||
@ -10,7 +10,6 @@ use pumpkin_macros::pumpkin_block;
|
|||||||
use pumpkin_world::item::ItemStack;
|
use pumpkin_world::item::ItemStack;
|
||||||
use pumpkin_world::world::BlockFlags;
|
use pumpkin_world::world::BlockFlags;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
#[pumpkin_block("minecraft:pumpkin")]
|
#[pumpkin_block("minecraft:pumpkin")]
|
||||||
pub struct PumpkinBlock;
|
pub struct PumpkinBlock;
|
||||||
@ -39,11 +38,9 @@ impl crate::block::BlockBehaviour for PumpkinBlock {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(
|
||||||
Uuid::new_v4(),
|
|
||||||
args.world.clone(),
|
args.world.clone(),
|
||||||
args.position.to_f64(),
|
args.position.to_f64(),
|
||||||
&EntityType::ITEM,
|
&EntityType::ITEM,
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
let item_entity =
|
let item_entity =
|
||||||
Arc::new(ItemEntity::new(entity, ItemStack::new(4, &Item::PUMPKIN_SEEDS)).await);
|
Arc::new(ItemEntity::new(entity, ItemStack::new(4, &Item::PUMPKIN_SEEDS)).await);
|
||||||
|
|||||||
@ -28,7 +28,6 @@ use pumpkin_world::world::BlockFlags;
|
|||||||
use rand::{Rng, rng};
|
use rand::{Rng, rng};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
struct DropperScreenFactory(Arc<dyn Inventory>);
|
struct DropperScreenFactory(Arc<dyn Inventory>);
|
||||||
|
|
||||||
@ -200,13 +199,7 @@ impl BlockBehaviour for DropperBlock {
|
|||||||
Facing::Up | Facing::Down => 0.125,
|
Facing::Up | Facing::Down => 0.125,
|
||||||
_ => 0.15625,
|
_ => 0.15625,
|
||||||
};
|
};
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(args.world.clone(), position, &EntityType::ITEM);
|
||||||
Uuid::new_v4(),
|
|
||||||
args.world.clone(),
|
|
||||||
position,
|
|
||||||
&EntityType::ITEM,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let rd = rng().random::<f64>() * 0.1 + 0.2;
|
let rd = rng().random::<f64>() * 0.1 + 0.2;
|
||||||
let velocity = Vector3::new(
|
let velocity = Vector3::new(
|
||||||
triangle(&mut rng(), facing.x * rd, 0.017_227_5 * 6.),
|
triangle(&mut rng(), facing.x * rd, 0.017_227_5 * 6.),
|
||||||
|
|||||||
@ -15,7 +15,6 @@ use pumpkin_util::math::position::BlockPos;
|
|||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use pumpkin_world::world::BlockFlags;
|
use pumpkin_world::world::BlockFlags;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use super::redstone::block_receives_redstone_power;
|
use super::redstone::block_receives_redstone_power;
|
||||||
|
|
||||||
@ -24,13 +23,7 @@ pub struct TNTBlock;
|
|||||||
|
|
||||||
impl TNTBlock {
|
impl TNTBlock {
|
||||||
pub async fn prime(world: &Arc<World>, location: &BlockPos) {
|
pub async fn prime(world: &Arc<World>, location: &BlockPos) {
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), location.to_f64(), &EntityType::TNT);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
location.to_f64(),
|
|
||||||
&EntityType::TNT,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let pos = entity.pos.load();
|
let pos = entity.pos.load();
|
||||||
let tnt = Arc::new(TNTEntity::new(entity, DEFAULT_POWER, DEFAULT_FUSE));
|
let tnt = Arc::new(TNTEntity::new(entity, DEFAULT_POWER, DEFAULT_FUSE));
|
||||||
world.spawn_entity(tnt).await;
|
world.spawn_entity(tnt).await;
|
||||||
@ -85,13 +78,7 @@ impl BlockBehaviour for TNTBlock {
|
|||||||
|
|
||||||
fn explode<'a>(&'a self, args: ExplodeArgs<'a>) -> BlockFuture<'a, ()> {
|
fn explode<'a>(&'a self, args: ExplodeArgs<'a>) -> BlockFuture<'a, ()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(args.world.clone(), args.position.to_f64(), &EntityType::TNT);
|
||||||
Uuid::new_v4(),
|
|
||||||
args.world.clone(),
|
|
||||||
args.position.to_f64(),
|
|
||||||
&EntityType::TNT,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let angle = rand::random::<f64>() * std::f64::consts::TAU;
|
let angle = rand::random::<f64>() * std::f64::consts::TAU;
|
||||||
entity
|
entity
|
||||||
.set_velocity(Vector3::new(-angle.sin() * 0.02, 0.2, -angle.cos() * 0.02))
|
.set_velocity(Vector3::new(-angle.sin() * 0.02, 0.2, -angle.cos() * 0.02))
|
||||||
|
|||||||
0
pumpkin/src/block/blocks/wither_skull.rs
Normal file
0
pumpkin/src/block/blocks/wither_skull.rs
Normal file
@ -6,7 +6,6 @@ use std::sync::{
|
|||||||
|
|
||||||
use pumpkin_data::entity::EntityType;
|
use pumpkin_data::entity::EntityType;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::{entity::EntityBaseFuture, server::Server, world::World};
|
use crate::{entity::EntityBaseFuture, server::Server, world::World};
|
||||||
|
|
||||||
@ -33,13 +32,7 @@ impl ExperienceOrbEntity {
|
|||||||
while amount > 0 {
|
while amount > 0 {
|
||||||
let i = Self::round_to_orb_size(amount);
|
let i = Self::round_to_orb_size(amount);
|
||||||
amount -= i;
|
amount -= i;
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), position, &EntityType::EXPERIENCE_ORB);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
position,
|
|
||||||
&EntityType::EXPERIENCE_ORB,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let orb = Arc::new(Self::new(entity, i));
|
let orb = Arc::new(Self::new(entity, i));
|
||||||
world.spawn_entity(orb).await;
|
world.spawn_entity(orb).await;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use pumpkin_protocol::java::client::play::Metadata;
|
|||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_world::{BlockStateId, world::BlockFlags};
|
use pumpkin_world::{BlockStateId, world::BlockFlags};
|
||||||
use std::sync::{Arc, atomic::Ordering};
|
use std::sync::{Arc, atomic::Ordering};
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entity::{Entity, EntityBase, EntityBaseFuture, NBTStorage, living::LivingEntity},
|
entity::{Entity, EntityBase, EntityBaseFuture, NBTStorage, living::LivingEntity},
|
||||||
@ -38,13 +37,7 @@ impl FallingEntity {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let position = position.0.to_f64().add_raw(0.5, 0.0, 0.5);
|
let position = position.0.to_f64().add_raw(0.5, 0.0, 0.5);
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), position, &EntityType::FALLING_BLOCK);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
position,
|
|
||||||
&EntityType::FALLING_BLOCK,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
entity.data.store(i32::from(block_state), Ordering::Relaxed);
|
entity.data.store(i32::from(block_state), Ordering::Relaxed);
|
||||||
let entity = Arc::new(Self::new(entity, block_state));
|
let entity = Arc::new(Self::new(entity, block_state));
|
||||||
world.spawn_entity(entity).await;
|
world.spawn_entity(entity).await;
|
||||||
|
|||||||
@ -51,6 +51,7 @@ use std::sync::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub mod ai;
|
pub mod ai;
|
||||||
pub mod decoration;
|
pub mod decoration;
|
||||||
@ -368,11 +369,18 @@ pub struct Entity {
|
|||||||
|
|
||||||
impl Entity {
|
impl Entity {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
world: Arc<World>,
|
||||||
|
position: Vector3<f64>,
|
||||||
|
entity_type: &'static EntityType,
|
||||||
|
) -> Self {
|
||||||
|
Self::from_uuid(Uuid::new_v4(), world, position, entity_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_uuid(
|
||||||
entity_uuid: uuid::Uuid,
|
entity_uuid: uuid::Uuid,
|
||||||
world: Arc<World>,
|
world: Arc<World>,
|
||||||
position: Vector3<f64>,
|
position: Vector3<f64>,
|
||||||
entity_type: &'static EntityType,
|
entity_type: &'static EntityType,
|
||||||
invulnerable: bool,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let floor_x = position.x.floor() as i32;
|
let floor_x = position.x.floor() as i32;
|
||||||
let floor_y = position.y.floor() as i32;
|
let floor_y = position.y.floor() as i32;
|
||||||
@ -421,7 +429,7 @@ impl Entity {
|
|||||||
&bounding_box_size,
|
&bounding_box_size,
|
||||||
)),
|
)),
|
||||||
entity_dimension: AtomicCell::new(bounding_box_size),
|
entity_dimension: AtomicCell::new(bounding_box_size),
|
||||||
invulnerable: AtomicBool::new(invulnerable),
|
invulnerable: AtomicBool::new(false),
|
||||||
damage_immunities: Vec::new(),
|
damage_immunities: Vec::new(),
|
||||||
data: AtomicI32::new(0),
|
data: AtomicI32::new(0),
|
||||||
fire_ticks: AtomicI32::new(-1),
|
fire_ticks: AtomicI32::new(-1),
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
|
pub mod snow_golem;
|
||||||
pub mod wolf;
|
pub mod wolf;
|
||||||
|
|||||||
46
pumpkin/src/entity/passive/snow_golem.rs
Normal file
46
pumpkin/src/entity/passive/snow_golem.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
|
use pumpkin_data::entity::EntityType;
|
||||||
|
|
||||||
|
use crate::entity::{
|
||||||
|
Entity, NBTStorage,
|
||||||
|
ai::goal::{look_around::LookAroundGoal, look_at_entity::LookAtEntityGoal},
|
||||||
|
mob::{Mob, MobEntity},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct SnowGolemEntity {
|
||||||
|
pub mob_entity: MobEntity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SnowGolemEntity {
|
||||||
|
pub async fn make(entity: Entity) -> Arc<Self> {
|
||||||
|
let mob_entity = MobEntity::new(entity);
|
||||||
|
let wolf = Self { mob_entity };
|
||||||
|
let mob_arc = Arc::new(wolf);
|
||||||
|
let mob_weak: Weak<dyn Mob> = {
|
||||||
|
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
|
||||||
|
Arc::downgrade(&mob_arc)
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
goal_selector.add_goal(
|
||||||
|
8,
|
||||||
|
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
|
||||||
|
);
|
||||||
|
goal_selector.add_goal(8, Box::new(LookAroundGoal::default()));
|
||||||
|
};
|
||||||
|
|
||||||
|
mob_arc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NBTStorage for SnowGolemEntity {}
|
||||||
|
|
||||||
|
impl Mob for SnowGolemEntity {
|
||||||
|
fn get_mob_entity(&self) -> &MobEntity {
|
||||||
|
&self.mob_entity
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -426,13 +426,16 @@ impl Player {
|
|||||||
|
|
||||||
let player_uuid = gameprofile.id;
|
let player_uuid = gameprofile.id;
|
||||||
|
|
||||||
let living_entity = LivingEntity::new(Entity::new(
|
let living_entity = LivingEntity::new(Entity::from_uuid(
|
||||||
player_uuid,
|
player_uuid,
|
||||||
world.clone(),
|
world.clone(),
|
||||||
Vector3::new(0.0, 100.0, 0.0),
|
Vector3::new(0.0, 100.0, 0.0),
|
||||||
&EntityType::PLAYER,
|
&EntityType::PLAYER,
|
||||||
matches!(gamemode, GameMode::Creative | GameMode::Spectator),
|
|
||||||
));
|
));
|
||||||
|
living_entity.entity.invulnerable.store(
|
||||||
|
matches!(gamemode, GameMode::Creative | GameMode::Spectator),
|
||||||
|
Ordering::Relaxed,
|
||||||
|
);
|
||||||
|
|
||||||
let inventory = Arc::new(PlayerInventory::new(
|
let inventory = Arc::new(PlayerInventory::new(
|
||||||
living_entity.entity_equipment.clone(),
|
living_entity.entity_equipment.clone(),
|
||||||
@ -1723,13 +1726,7 @@ impl Player {
|
|||||||
pub async fn drop_item(&self, item_stack: ItemStack) {
|
pub async fn drop_item(&self, item_stack: ItemStack) {
|
||||||
let item_pos = self.living_entity.entity.pos.load()
|
let item_pos = self.living_entity.entity.pos.load()
|
||||||
+ Vector3::new(0.0, f64::from(EntityType::PLAYER.eye_height) - 0.3, 0.0);
|
+ Vector3::new(0.0, f64::from(EntityType::PLAYER.eye_height) - 0.3, 0.0);
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(self.world().clone(), item_pos, &EntityType::ITEM);
|
||||||
Uuid::new_v4(),
|
|
||||||
self.world().clone(),
|
|
||||||
item_pos,
|
|
||||||
&EntityType::ITEM,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let pitch = f64::from(self.living_entity.entity.pitch.load()).to_radians();
|
let pitch = f64::from(self.living_entity.entity.pitch.load()).to_radians();
|
||||||
let yaw = f64::from(self.living_entity.entity.yaw.load()).to_radians();
|
let yaw = f64::from(self.living_entity.entity.yaw.load()).to_radians();
|
||||||
|
|||||||
@ -15,7 +15,7 @@ use crate::{
|
|||||||
creeper::CreeperEntity, drowned::DrownedEntity, zombie::ZombieEntity,
|
creeper::CreeperEntity, drowned::DrownedEntity, zombie::ZombieEntity,
|
||||||
zombie_villager::ZombieVillagerEntity,
|
zombie_villager::ZombieVillagerEntity,
|
||||||
},
|
},
|
||||||
passive::wolf::WolfEntity,
|
passive::{snow_golem::SnowGolemEntity, wolf::WolfEntity},
|
||||||
},
|
},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
@ -26,13 +26,14 @@ pub async fn from_type(
|
|||||||
world: &Arc<World>,
|
world: &Arc<World>,
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
) -> Arc<dyn EntityBase> {
|
) -> Arc<dyn EntityBase> {
|
||||||
let entity = Entity::new(uuid, world.clone(), position, entity_type, false);
|
let entity = Entity::from_uuid(uuid, world.clone(), position, entity_type);
|
||||||
|
|
||||||
let mob: Arc<dyn EntityBase> = match entity_type.id {
|
let mob: Arc<dyn EntityBase> = match entity_type.id {
|
||||||
id if id == EntityType::ZOMBIE.id => ZombieEntity::make(entity).await,
|
id if id == EntityType::ZOMBIE.id => ZombieEntity::make(entity).await,
|
||||||
id if id == EntityType::DROWNED.id => DrownedEntity::make(entity).await,
|
id if id == EntityType::DROWNED.id => DrownedEntity::make(entity).await,
|
||||||
id if id == EntityType::ZOMBIE_VILLAGER.id => ZombieVillagerEntity::make(entity).await,
|
id if id == EntityType::ZOMBIE_VILLAGER.id => ZombieVillagerEntity::make(entity).await,
|
||||||
id if id == EntityType::CREEPER.id => CreeperEntity::make(entity).await,
|
id if id == EntityType::CREEPER.id => CreeperEntity::make(entity).await,
|
||||||
|
id if id == EntityType::SNOW_GOLEM.id => SnowGolemEntity::make(entity).await,
|
||||||
id if id == EntityType::WOLF.id => WolfEntity::make(entity).await,
|
id if id == EntityType::WOLF.id => WolfEntity::make(entity).await,
|
||||||
id if id == EntityType::ARMOR_STAND.id => Arc::new(ArmorStandEntity::new(entity)),
|
id if id == EntityType::ARMOR_STAND.id => Arc::new(ArmorStandEntity::new(entity)),
|
||||||
id if id == EntityType::PAINTING.id => Arc::new(PaintingEntity::new(entity)),
|
id if id == EntityType::PAINTING.id => Arc::new(PaintingEntity::new(entity)),
|
||||||
|
|||||||
@ -15,7 +15,6 @@ use pumpkin_util::math::position::BlockPos;
|
|||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use pumpkin_util::math::wrap_degrees;
|
use pumpkin_util::math::wrap_degrees;
|
||||||
use pumpkin_world::item::ItemStack;
|
use pumpkin_world::item::ItemStack;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
pub struct ArmorStandItem;
|
pub struct ArmorStandItem;
|
||||||
|
|
||||||
@ -78,13 +77,7 @@ impl ItemBehaviour for ArmorStandItem {
|
|||||||
let (player_yaw, _) = player.rotation();
|
let (player_yaw, _) = player.rotation();
|
||||||
let rotation = ((wrap_degrees(player_yaw - 180.0) + 22.5) / 45.0).floor() * 45.0;
|
let rotation = ((wrap_degrees(player_yaw - 180.0) + 22.5) / 45.0).floor() * 45.0;
|
||||||
|
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), position, &EntityType::ARMOR_STAND);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
position,
|
|
||||||
&EntityType::ARMOR_STAND,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
entity.set_rotation(rotation, 0.0);
|
entity.set_rotation(rotation, 0.0);
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@ use crate::item::{ItemBehaviour, ItemMetadata};
|
|||||||
use pumpkin_data::entity::EntityType;
|
use pumpkin_data::entity::EntityType;
|
||||||
use pumpkin_data::item::Item;
|
use pumpkin_data::item::Item;
|
||||||
use pumpkin_data::sound::Sound;
|
use pumpkin_data::sound::Sound;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
pub struct EggItem;
|
pub struct EggItem;
|
||||||
|
|
||||||
@ -37,13 +36,7 @@ impl ItemBehaviour for EggItem {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
// TODO: Implement eggs the right way, so there is a chance of spawning chickens
|
// TODO: Implement eggs the right way, so there is a chance of spawning chickens
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), position, &EntityType::EGG);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
position,
|
|
||||||
&EntityType::EGG,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let egg = ThrownItemEntity::new(entity, &player.living_entity.entity);
|
let egg = ThrownItemEntity::new(entity, &player.living_entity.entity);
|
||||||
let yaw = player.living_entity.entity.yaw.load();
|
let yaw = player.living_entity.entity.yaw.load();
|
||||||
let pitch = player.living_entity.entity.pitch.load();
|
let pitch = player.living_entity.entity.pitch.load();
|
||||||
|
|||||||
@ -12,7 +12,6 @@ use pumpkin_data::{Block, BlockDirection};
|
|||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use pumpkin_world::item::ItemStack;
|
use pumpkin_world::item::ItemStack;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
pub struct EndCrystalItem;
|
pub struct EndCrystalItem;
|
||||||
|
|
||||||
@ -41,13 +40,7 @@ impl ItemBehaviour for EndCrystalItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let location = location.up();
|
let location = location.up();
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), location.to_f64(), &EntityType::END_CRYSTAL);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
location.to_f64(),
|
|
||||||
&EntityType::END_CRYSTAL,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let end_crystal = Arc::new(EndCrystalEntity::new(entity));
|
let end_crystal = Arc::new(EndCrystalEntity::new(entity));
|
||||||
world.spawn_entity(end_crystal.clone()).await;
|
world.spawn_entity(end_crystal.clone()).await;
|
||||||
end_crystal.set_show_bottom(false).await;
|
end_crystal.set_show_bottom(false).await;
|
||||||
|
|||||||
@ -14,7 +14,6 @@ use pumpkin_data::item::Item;
|
|||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use pumpkin_world::item::ItemStack;
|
use pumpkin_world::item::ItemStack;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
pub struct FireworkRocketItem;
|
pub struct FireworkRocketItem;
|
||||||
|
|
||||||
@ -38,7 +37,6 @@ impl ItemBehaviour for FireworkRocketItem {
|
|||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let world = player.world();
|
let world = player.world();
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
world.clone(),
|
||||||
Vector3::new(
|
Vector3::new(
|
||||||
f64::from(location.0.x) + f64::from(cursor_pos.x),
|
f64::from(location.0.x) + f64::from(cursor_pos.x),
|
||||||
@ -46,7 +44,6 @@ impl ItemBehaviour for FireworkRocketItem {
|
|||||||
f64::from(location.0.z) + f64::from(cursor_pos.z),
|
f64::from(location.0.z) + f64::from(cursor_pos.z),
|
||||||
),
|
),
|
||||||
&EntityType::FIREWORK_ROCKET,
|
&EntityType::FIREWORK_ROCKET,
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
let entity = FireworkRocketEntity::new(entity).await;
|
let entity = FireworkRocketEntity::new(entity).await;
|
||||||
world.spawn_entity(Arc::new(entity)).await;
|
world.spawn_entity(Arc::new(entity)).await;
|
||||||
@ -62,11 +59,9 @@ impl ItemBehaviour for FireworkRocketItem {
|
|||||||
if player.get_entity().fall_flying.load(Ordering::Relaxed) {
|
if player.get_entity().fall_flying.load(Ordering::Relaxed) {
|
||||||
let world = player.world();
|
let world = player.world();
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
world.clone(),
|
||||||
player.get_entity().pos.load(),
|
player.get_entity().pos.load(),
|
||||||
&EntityType::FIREWORK_ROCKET,
|
&EntityType::FIREWORK_ROCKET,
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
let entity = FireworkRocketEntity::new_shot(entity, player.get_entity()).await;
|
let entity = FireworkRocketEntity::new_shot(entity, player.get_entity()).await;
|
||||||
world.spawn_entity(Arc::new(entity)).await;
|
world.spawn_entity(Arc::new(entity)).await;
|
||||||
|
|||||||
@ -14,7 +14,6 @@ use pumpkin_world::item::ItemStack;
|
|||||||
use pumpkin_world::world::BlockFlags;
|
use pumpkin_world::world::BlockFlags;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
pub struct HoeItem;
|
pub struct HoeItem;
|
||||||
|
|
||||||
@ -88,13 +87,7 @@ impl ItemBehaviour for HoeItem {
|
|||||||
BlockDirection::West => location.up().to_f64().add_raw(-1.0, -0.4, 0.0),
|
BlockDirection::West => location.up().to_f64().add_raw(-1.0, -0.4, 0.0),
|
||||||
BlockDirection::East => location.up().to_f64().add_raw(1.0, -0.4, 0.0),
|
BlockDirection::East => location.up().to_f64().add_raw(1.0, -0.4, 0.0),
|
||||||
};
|
};
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), location, &EntityType::ITEM);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
location,
|
|
||||||
&EntityType::ITEM,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
// TODO: Merge stacks together
|
// TODO: Merge stacks together
|
||||||
let item_entity = Arc::new(
|
let item_entity = Arc::new(
|
||||||
ItemEntity::new(entity, ItemStack::new(1, &Item::HANGING_ROOTS)).await,
|
ItemEntity::new(entity, ItemStack::new(1, &Item::HANGING_ROOTS)).await,
|
||||||
|
|||||||
@ -16,7 +16,6 @@ use pumpkin_data::{Block, tag};
|
|||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use pumpkin_world::item::ItemStack;
|
use pumpkin_world::item::ItemStack;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
pub struct MinecartItem;
|
pub struct MinecartItem;
|
||||||
|
|
||||||
@ -79,11 +78,9 @@ impl ItemBehaviour for MinecartItem {
|
|||||||
let entity_type = Self::item_to_entity(item.item);
|
let entity_type = Self::item_to_entity(item.item);
|
||||||
let pos = location.to_f64();
|
let pos = location.to_f64();
|
||||||
let entity = Arc::new(Entity::new(
|
let entity = Arc::new(Entity::new(
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
world.clone(),
|
||||||
Vector3::new(pos.x, pos.y + 0.0625 + height, pos.z),
|
Vector3::new(pos.x, pos.y + 0.0625 + height, pos.z),
|
||||||
entity_type,
|
entity_type,
|
||||||
false,
|
|
||||||
));
|
));
|
||||||
world.spawn_entity(entity).await;
|
world.spawn_entity(entity).await;
|
||||||
})
|
})
|
||||||
|
|||||||
@ -8,7 +8,6 @@ use crate::item::{ItemBehaviour, ItemMetadata};
|
|||||||
use pumpkin_data::entity::EntityType;
|
use pumpkin_data::entity::EntityType;
|
||||||
use pumpkin_data::item::Item;
|
use pumpkin_data::item::Item;
|
||||||
use pumpkin_data::sound::Sound;
|
use pumpkin_data::sound::Sound;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
pub struct SnowBallItem;
|
pub struct SnowBallItem;
|
||||||
|
|
||||||
@ -36,13 +35,7 @@ impl ItemBehaviour for SnowBallItem {
|
|||||||
&position,
|
&position,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), position, &EntityType::SNOWBALL);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
position,
|
|
||||||
&EntityType::SNOWBALL,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let snowball = ThrownItemEntity::new(entity, &player.living_entity.entity);
|
let snowball = ThrownItemEntity::new(entity, &player.living_entity.entity);
|
||||||
let yaw = player.living_entity.entity.yaw.load();
|
let yaw = player.living_entity.entity.yaw.load();
|
||||||
let pitch = player.living_entity.entity.pitch.load();
|
let pitch = player.living_entity.entity.pitch.load();
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::entity::player::Player;
|
|||||||
use pumpkin_data::entity::EntityType;
|
use pumpkin_data::entity::EntityType;
|
||||||
use pumpkin_data::item::Item;
|
use pumpkin_data::item::Item;
|
||||||
use pumpkin_data::sound::Sound;
|
use pumpkin_data::sound::Sound;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::entity::Entity;
|
use crate::entity::Entity;
|
||||||
use crate::entity::projectile::ThrownItemEntity;
|
use crate::entity::projectile::ThrownItemEntity;
|
||||||
@ -42,13 +41,7 @@ impl ItemBehaviour for WindChargeItem {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(world.clone(), position, &EntityType::WIND_CHARGE);
|
||||||
Uuid::new_v4(),
|
|
||||||
world.clone(),
|
|
||||||
position,
|
|
||||||
&EntityType::WIND_CHARGE,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let wind_charge = ThrownItemEntity::new(entity, &player.living_entity.entity);
|
let wind_charge = ThrownItemEntity::new(entity, &player.living_entity.entity);
|
||||||
let yaw = player.living_entity.entity.yaw.load();
|
let yaw = player.living_entity.entity.yaw.load();
|
||||||
|
|||||||
@ -1126,20 +1126,16 @@ impl World {
|
|||||||
!= &Block::LIGHTNING_ROD
|
!= &Block::LIGHTNING_ROD
|
||||||
{
|
{
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(
|
||||||
Uuid::new_v4(),
|
|
||||||
self.clone(),
|
self.clone(),
|
||||||
random_pos.to_f64(),
|
random_pos.to_f64(),
|
||||||
&EntityType::SKELETON_HORSE,
|
&EntityType::SKELETON_HORSE,
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
self.spawn_entity(Arc::new(entity)).await;
|
self.spawn_entity(Arc::new(entity)).await;
|
||||||
}
|
}
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(
|
||||||
Uuid::new_v4(),
|
|
||||||
self.clone(),
|
self.clone(),
|
||||||
random_pos.to_f64().add_raw(0.5, 0., 0.5),
|
random_pos.to_f64().add_raw(0.5, 0., 0.5),
|
||||||
&EntityType::LIGHTNING_BOLT,
|
&EntityType::LIGHTNING_BOLT,
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
self.spawn_entity(Arc::new(entity)).await;
|
self.spawn_entity(Arc::new(entity)).await;
|
||||||
}
|
}
|
||||||
@ -2762,7 +2758,7 @@ impl World {
|
|||||||
f64::from(pos.0.z) + 0.5 + rand::rng().random_range(-0.25..0.25),
|
f64::from(pos.0.z) + 0.5 + rand::rng().random_range(-0.25..0.25),
|
||||||
);
|
);
|
||||||
|
|
||||||
let entity = Entity::new(Uuid::new_v4(), self.clone(), pos, &EntityType::ITEM, false);
|
let entity = Entity::new(self.clone(), pos, &EntityType::ITEM);
|
||||||
let item_entity = Arc::new(ItemEntity::new(entity, stack).await);
|
let item_entity = Arc::new(ItemEntity::new(entity, stack).await);
|
||||||
self.spawn_entity(item_entity).await;
|
self.spawn_entity(item_entity).await;
|
||||||
}
|
}
|
||||||
@ -2808,13 +2804,7 @@ impl World {
|
|||||||
rng.next_triangular(XZ_MODE, TRIANGULAR_DEVIATION),
|
rng.next_triangular(XZ_MODE, TRIANGULAR_DEVIATION),
|
||||||
);
|
);
|
||||||
|
|
||||||
let entity = Entity::new(
|
let entity = Entity::new(self.clone(), Vector3::new(x, y, z), &EntityType::ITEM);
|
||||||
Uuid::new_v4(),
|
|
||||||
self.clone(),
|
|
||||||
Vector3::new(x, y, z),
|
|
||||||
&EntityType::ITEM,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let entity = Arc::new(ItemEntity::new_with_velocity(entity, item, velocity, 10).await);
|
let entity = Arc::new(ItemEntity::new_with_velocity(entity, item, velocity, 10).await);
|
||||||
self.spawn_entity(entity).await;
|
self.spawn_entity(entity).await;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user