mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-31 08:22:33 +00:00
Don't require server when spawning a entity
Makes it much simpler
This commit is contained in:
@@ -29,14 +29,14 @@ impl PumpkinBlock for TNTBlock {
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
item: &Item,
|
||||
server: &Server,
|
||||
_server: &Server,
|
||||
) -> BlockActionResult {
|
||||
if *item != Item::FLINT_AND_STEEL || *item == Item::FIRE_CHARGE {
|
||||
return BlockActionResult::Continue;
|
||||
}
|
||||
let world = player.world().await;
|
||||
world.set_block_state(&location, 0).await;
|
||||
let entity = server.add_entity(location.to_f64(), EntityType::TNT, &world);
|
||||
let entity = world.create_entity(location.to_f64(), EntityType::TNT);
|
||||
let pos = entity.pos.load();
|
||||
let tnt = Arc::new(TNTEntity::new(entity, DEFAULT_POWER, DEFAULT_FUSE));
|
||||
world.spawn_entity(tnt.clone()).await;
|
||||
@@ -50,14 +50,8 @@ impl PumpkinBlock for TNTBlock {
|
||||
.await;
|
||||
BlockActionResult::Consume
|
||||
}
|
||||
async fn explode(
|
||||
&self,
|
||||
_block: &Block,
|
||||
world: &Arc<World>,
|
||||
location: BlockPos,
|
||||
server: &Server,
|
||||
) {
|
||||
let entity = server.add_entity(location.to_f64(), EntityType::TNT, world);
|
||||
async fn explode(&self, _block: &Block, world: &Arc<World>, location: BlockPos) {
|
||||
let entity = world.create_entity(location.to_f64(), EntityType::TNT);
|
||||
let fuse = rand::thread_rng().gen_range(0..DEFAULT_FUSE / 4) + DEFAULT_FUSE / 8;
|
||||
let tnt = Arc::new(TNTEntity::new(entity, DEFAULT_POWER, fuse));
|
||||
world.spawn_entity(tnt.clone()).await;
|
||||
|
||||
@@ -28,7 +28,6 @@ use rand::Rng;
|
||||
|
||||
use crate::block::registry::BlockRegistry;
|
||||
use crate::entity::item::ItemEntity;
|
||||
use crate::server::Server;
|
||||
use crate::world::World;
|
||||
use crate::{block::blocks::crafting_table::CraftingTableBlock, entity::player::Player};
|
||||
use crate::{block::blocks::jukebox::JukeboxBlock, entity::experience_orb::ExperienceOrbEntity};
|
||||
@@ -53,17 +52,11 @@ pub fn default_registry() -> Arc<BlockRegistry> {
|
||||
Arc::new(manager)
|
||||
}
|
||||
|
||||
pub async fn drop_loot(
|
||||
server: &Server,
|
||||
world: &Arc<World>,
|
||||
block: &Block,
|
||||
pos: &BlockPos,
|
||||
experience: bool,
|
||||
) {
|
||||
pub async fn drop_loot(world: &Arc<World>, block: &Block, pos: &BlockPos, experience: bool) {
|
||||
if let Some(table) = &block.loot_table {
|
||||
let loot = table.get_loot();
|
||||
for item in loot {
|
||||
drop_stack(server, world, pos, item).await;
|
||||
drop_stack(world, pos, item).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,13 +65,13 @@ pub async fn drop_loot(
|
||||
let amount = experience.experience.get();
|
||||
// TODO: Silk touch gives no exp
|
||||
if amount > 0 {
|
||||
ExperienceOrbEntity::spawn(world, server, pos.to_f64(), amount as u32).await;
|
||||
ExperienceOrbEntity::spawn(world, pos.to_f64(), amount as u32).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn drop_stack(server: &Server, world: &Arc<World>, pos: &BlockPos, stack: ItemStack) {
|
||||
async fn drop_stack(world: &Arc<World>, pos: &BlockPos, stack: ItemStack) {
|
||||
let height = EntityType::ITEM.dimension[1] / 2.0;
|
||||
let pos = Vector3::new(
|
||||
f64::from(pos.0.x) + 0.5 + rand::thread_rng().gen_range(-0.25..0.25),
|
||||
@@ -86,7 +79,7 @@ async fn drop_stack(server: &Server, world: &Arc<World>, pos: &BlockPos, stack:
|
||||
f64::from(pos.0.z) + 0.5 + rand::thread_rng().gen_range(-0.25..0.25),
|
||||
);
|
||||
|
||||
let entity = server.add_entity(pos, EntityType::ITEM, world);
|
||||
let entity = world.create_entity(pos, EntityType::ITEM);
|
||||
let item_entity = Arc::new(ItemEntity::new(
|
||||
entity,
|
||||
stack.item.id,
|
||||
|
||||
@@ -34,14 +34,7 @@ pub trait PumpkinBlock: Send + Sync {
|
||||
fn should_drop_items_on_explosion(&self) -> bool {
|
||||
true
|
||||
}
|
||||
async fn explode(
|
||||
&self,
|
||||
_block: &Block,
|
||||
_world: &Arc<World>,
|
||||
_location: BlockPos,
|
||||
_server: &Server,
|
||||
) {
|
||||
}
|
||||
async fn explode(&self, _block: &Block, _world: &Arc<World>, _location: BlockPos) {}
|
||||
async fn use_with_item(
|
||||
&self,
|
||||
_block: &Block,
|
||||
|
||||
@@ -45,16 +45,10 @@ impl BlockRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn explode(
|
||||
&self,
|
||||
block: &Block,
|
||||
world: &Arc<World>,
|
||||
location: BlockPos,
|
||||
server: &Server,
|
||||
) {
|
||||
pub async fn explode(&self, block: &Block, world: &Arc<World>, location: BlockPos) {
|
||||
let pumpkin_block = self.get_pumpkin_block(block);
|
||||
if let Some(pumpkin_block) = pumpkin_block {
|
||||
pumpkin_block.explode(block, world, location, server).await;
|
||||
pumpkin_block.explode(block, world, location).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
server: &crate::server::Server,
|
||||
_server: &crate::server::Server,
|
||||
args: &ConsumedArgs<'a>,
|
||||
) -> Result<(), CommandError> {
|
||||
let block = BlockArgumentConsumer::find_arg(args, ARG_BLOCK)?;
|
||||
@@ -70,9 +70,7 @@ impl CommandExecutor for Executor {
|
||||
for y in start_y..=end_y {
|
||||
for z in start_z..=end_z {
|
||||
let block_position = BlockPos(Vector3 { x, y, z });
|
||||
world
|
||||
.break_block(server, &block_position, None, false)
|
||||
.await;
|
||||
world.break_block(&block_position, None, false).await;
|
||||
world.set_block_state(&block_position, block_state_id).await;
|
||||
placed_blocks += 1;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
server: &crate::server::Server,
|
||||
_server: &crate::server::Server,
|
||||
args: &ConsumedArgs<'a>,
|
||||
) -> Result<(), CommandError> {
|
||||
let block = BlockArgumentConsumer::find_arg(args, ARG_BLOCK)?;
|
||||
@@ -49,7 +49,7 @@ impl CommandExecutor for Executor {
|
||||
|
||||
let success = match mode {
|
||||
Mode::Destroy => {
|
||||
world.clone().break_block(server, &pos, None, false).await;
|
||||
world.clone().break_block(&pos, None, false).await;
|
||||
world.set_block_state(&pos, block_state_id).await;
|
||||
true
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
server: &crate::server::Server,
|
||||
_server: &crate::server::Server,
|
||||
args: &ConsumedArgs<'a>,
|
||||
) -> Result<(), CommandError> {
|
||||
let entity = SummonableEntitiesArgumentConsumer::find_arg(args, ARG_ENTITY)?;
|
||||
@@ -37,7 +37,7 @@ impl CommandExecutor for Executor {
|
||||
// TODO: Make this work in console
|
||||
if let Some(player) = sender.as_player() {
|
||||
let pos = pos.unwrap_or(player.living_entity.entity.pos.load());
|
||||
let mob = mob::from_type(entity, server, pos, &player.world().await).await;
|
||||
let mob = mob::from_type(entity, pos, &player.world().await).await;
|
||||
player.world().await.spawn_entity(mob).await;
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
|
||||
@@ -24,12 +24,12 @@ impl ExperienceOrbEntity {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn spawn(world: &Arc<World>, server: &Server, position: Vector3<f64>, amount: u32) {
|
||||
pub async fn spawn(world: &Arc<World>, position: Vector3<f64>, amount: u32) {
|
||||
let mut amount = amount;
|
||||
while amount > 0 {
|
||||
let i = Self::round_to_orb_size(amount);
|
||||
amount -= i;
|
||||
let entity = server.add_entity(position, EntityType::EXPERIENCE_ORB, world);
|
||||
let entity = world.create_entity(position, EntityType::EXPERIENCE_ORB);
|
||||
let orb = Arc::new(Self::new(entity, i));
|
||||
world.spawn_entity(orb).await;
|
||||
}
|
||||
|
||||
@@ -53,11 +53,10 @@ impl EntityBase for MobEntity {
|
||||
|
||||
pub async fn from_type(
|
||||
entity_type: EntityType,
|
||||
server: &Server,
|
||||
position: Vector3<f64>,
|
||||
world: &Arc<World>,
|
||||
) -> Arc<dyn EntityBase> {
|
||||
let entity = server.add_entity(position, entity_type, world);
|
||||
let entity = world.create_entity(position, entity_type);
|
||||
let mob = MobEntity {
|
||||
living_entity: LivingEntity::new(entity),
|
||||
goals: Mutex::new(vec![]),
|
||||
|
||||
@@ -28,7 +28,10 @@ use pumpkin_util::math::{
|
||||
wrap_degrees,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use std::sync::{Arc, atomic::AtomicBool};
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicI32},
|
||||
};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::world::World;
|
||||
@@ -74,6 +77,8 @@ pub trait EntityBase: Send + Sync {
|
||||
fn get_living_entity(&self) -> Option<&LivingEntity>;
|
||||
}
|
||||
|
||||
static CURRENT_ID: AtomicI32 = AtomicI32::new(0);
|
||||
|
||||
/// Represents a not living Entity (e.g. Item, Egg, Snowball...)
|
||||
pub struct Entity {
|
||||
/// A unique identifier for the entity
|
||||
@@ -121,24 +126,24 @@ pub struct Entity {
|
||||
}
|
||||
|
||||
impl Entity {
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
entity_id: EntityId,
|
||||
entity_uuid: uuid::Uuid,
|
||||
world: Arc<World>,
|
||||
position: Vector3<f64>,
|
||||
entity_type: EntityType,
|
||||
standing_eye_height: f32,
|
||||
bounding_box: AtomicCell<BoundingBox>,
|
||||
bounding_box_size: AtomicCell<EntityDimensions>,
|
||||
invulnerable: bool,
|
||||
) -> Self {
|
||||
let floor_x = position.x.floor() as i32;
|
||||
let floor_y = position.y.floor() as i32;
|
||||
let floor_z = position.z.floor() as i32;
|
||||
|
||||
let bounding_box_size = EntityDimensions {
|
||||
width: entity_type.dimension[0],
|
||||
height: entity_type.dimension[1],
|
||||
};
|
||||
|
||||
Self {
|
||||
entity_id,
|
||||
entity_id: CURRENT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
|
||||
entity_uuid,
|
||||
entity_type,
|
||||
on_ground: AtomicBool::new(false),
|
||||
@@ -154,10 +159,15 @@ impl Entity {
|
||||
head_yaw: AtomicCell::new(0.0),
|
||||
pitch: AtomicCell::new(0.0),
|
||||
velocity: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)),
|
||||
standing_eye_height,
|
||||
standing_eye_height: entity_type.eye_height,
|
||||
pose: AtomicCell::new(EntityPose::Standing),
|
||||
bounding_box,
|
||||
bounding_box_size,
|
||||
bounding_box: AtomicCell::new(BoundingBox::new_from_pos(
|
||||
position.x,
|
||||
position.y,
|
||||
position.z,
|
||||
&bounding_box_size,
|
||||
)),
|
||||
bounding_box_size: AtomicCell::new(bounding_box_size),
|
||||
invulnerable: AtomicBool::new(invulnerable),
|
||||
damage_immunities: Vec::new(),
|
||||
}
|
||||
|
||||
@@ -51,10 +51,7 @@ use pumpkin_protocol::{
|
||||
use pumpkin_util::{
|
||||
GameMode,
|
||||
math::{
|
||||
boundingbox::{BoundingBox, EntityDimensions},
|
||||
experience,
|
||||
position::BlockPos,
|
||||
vector2::Vector2,
|
||||
boundingbox::BoundingBox, experience, position::BlockPos, vector2::Vector2,
|
||||
vector3::Vector3,
|
||||
},
|
||||
permission::PermissionLvl,
|
||||
@@ -151,12 +148,7 @@ pub struct Player {
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub async fn new(
|
||||
client: Arc<Client>,
|
||||
world: Arc<World>,
|
||||
entity_id: EntityId,
|
||||
gamemode: GameMode,
|
||||
) -> Self {
|
||||
pub async fn new(client: Arc<Client>, world: Arc<World>, gamemode: GameMode) -> Self {
|
||||
let gameprofile = client.gameprofile.lock().await.clone().map_or_else(
|
||||
|| {
|
||||
log::error!("Client {} has no game profile!", client.id);
|
||||
@@ -173,21 +165,13 @@ impl Player {
|
||||
|
||||
let gameprofile_clone = gameprofile.clone();
|
||||
let config = client.config.lock().await.clone().unwrap_or_default();
|
||||
let bounding_box_size = EntityDimensions {
|
||||
width: EntityType::PLAYER.dimension[0],
|
||||
height: EntityType::PLAYER.dimension[1],
|
||||
};
|
||||
|
||||
Self {
|
||||
living_entity: LivingEntity::new(Entity::new(
|
||||
entity_id,
|
||||
player_uuid,
|
||||
world,
|
||||
Vector3::new(0.0, 0.0, 0.0),
|
||||
EntityType::PLAYER,
|
||||
EntityType::PLAYER.eye_height,
|
||||
AtomicCell::new(BoundingBox::new_default(&bounding_box_size)),
|
||||
AtomicCell::new(bounding_box_size),
|
||||
matches!(gamemode, GameMode::Creative | GameMode::Spectator),
|
||||
)),
|
||||
config: Mutex::new(config),
|
||||
@@ -1018,12 +1002,11 @@ impl Player {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn drop_item(&self, server: &Server, item_id: u16, count: u32) {
|
||||
let entity = server.add_entity(
|
||||
self.living_entity.entity.pos.load(),
|
||||
EntityType::ITEM,
|
||||
&self.world().await,
|
||||
);
|
||||
pub async fn drop_item(&self, item_id: u16, count: u32) {
|
||||
let entity = self
|
||||
.world()
|
||||
.await
|
||||
.create_entity(self.living_entity.entity.pos.load(), EntityType::ITEM);
|
||||
|
||||
// TODO: Merge stacks together
|
||||
let item_entity = Arc::new(ItemEntity::new(entity, item_id, count));
|
||||
@@ -1031,11 +1014,11 @@ impl Player {
|
||||
item_entity.send_meta_packet().await;
|
||||
}
|
||||
|
||||
pub async fn drop_held_item(&self, server: &Server, drop_stack: bool) {
|
||||
pub async fn drop_held_item(&self, drop_stack: bool) {
|
||||
let mut inv = self.inventory.lock().await;
|
||||
if let Some(item_stack) = inv.held_item_mut() {
|
||||
let drop_amount = if drop_stack { item_stack.item_count } else { 1 };
|
||||
self.drop_item(server, item_stack.item.id, u32::from(drop_amount))
|
||||
self.drop_item(item_stack.item.id, u32::from(drop_amount))
|
||||
.await;
|
||||
inv.decrease_current_stack(drop_amount);
|
||||
}
|
||||
@@ -1323,7 +1306,7 @@ impl Player {
|
||||
.await;
|
||||
}
|
||||
SSetCreativeSlot::PACKET_ID => {
|
||||
self.handle_set_creative_slot(server, SSetCreativeSlot::read(bytebuf)?)
|
||||
self.handle_set_creative_slot(SSetCreativeSlot::read(bytebuf)?)
|
||||
.await?;
|
||||
}
|
||||
SSwingArm::PACKET_ID => {
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::sync::Arc;
|
||||
use crate::entity::player::Player;
|
||||
use crate::entity::projectile::ThrownItemEntity;
|
||||
use crate::item::pumpkin_item::PumpkinItem;
|
||||
use crate::server::Server;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_data::item::Item;
|
||||
@@ -17,7 +16,7 @@ const POWER: f32 = 1.5;
|
||||
|
||||
#[async_trait]
|
||||
impl PumpkinItem for EggItem {
|
||||
async fn normal_use(&self, _block: &Item, player: &Player, server: &Server) {
|
||||
async fn normal_use(&self, _block: &Item, player: &Player) {
|
||||
let position = player.position();
|
||||
let world = player.world().await;
|
||||
world
|
||||
@@ -28,7 +27,7 @@ impl PumpkinItem for EggItem {
|
||||
)
|
||||
.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 entity = world.create_entity(position, EntityType::EGG);
|
||||
let snowball = ThrownItemEntity::new(entity, &player.living_entity.entity);
|
||||
let yaw = player.living_entity.entity.yaw.load();
|
||||
let pitch = player.living_entity.entity.pitch.load();
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::sync::Arc;
|
||||
use crate::entity::player::Player;
|
||||
use crate::entity::projectile::ThrownItemEntity;
|
||||
use crate::item::pumpkin_item::PumpkinItem;
|
||||
use crate::server::Server;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_data::item::Item;
|
||||
@@ -17,7 +16,7 @@ const POWER: f32 = 1.5;
|
||||
|
||||
#[async_trait]
|
||||
impl PumpkinItem for SnowBallItem {
|
||||
async fn normal_use(&self, _block: &Item, player: &Player, server: &Server) {
|
||||
async fn normal_use(&self, _block: &Item, player: &Player) {
|
||||
let position = player.position();
|
||||
let world = player.world().await;
|
||||
world
|
||||
@@ -27,7 +26,7 @@ impl PumpkinItem for SnowBallItem {
|
||||
&position,
|
||||
)
|
||||
.await;
|
||||
let entity = server.add_entity(position, EntityType::SNOWBALL, &world);
|
||||
let entity = world.create_entity(position, EntityType::SNOWBALL);
|
||||
let snowball = ThrownItemEntity::new(entity, &player.living_entity.entity);
|
||||
let yaw = player.living_entity.entity.yaw.load();
|
||||
let pitch = player.living_entity.entity.pitch.load();
|
||||
|
||||
@@ -11,7 +11,7 @@ pub trait ItemMetadata {
|
||||
|
||||
#[async_trait]
|
||||
pub trait PumpkinItem: Send + Sync {
|
||||
async fn normal_use(&self, _block: &Item, _player: &Player, _server: &Server) {}
|
||||
async fn normal_use(&self, _block: &Item, _player: &Player) {}
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
|
||||
@@ -18,10 +18,10 @@ impl ItemRegistry {
|
||||
self.items.insert(T::ID, Arc::new(item));
|
||||
}
|
||||
|
||||
pub async fn on_use(&self, item: &Item, player: &Player, server: &Server) {
|
||||
pub async fn on_use(&self, item: &Item, player: &Player) {
|
||||
let pumpkin_block = self.get_pumpkin_item(item.id);
|
||||
if let Some(pumpkin_block) = pumpkin_block {
|
||||
pumpkin_block.normal_use(item, player, server).await;
|
||||
pumpkin_block.normal_use(item, player).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,6 @@ impl Player {
|
||||
|
||||
let click_slot = click.slot;
|
||||
self.match_click_behaviour(
|
||||
server,
|
||||
opened_container.as_deref_mut(),
|
||||
click,
|
||||
drag_handler,
|
||||
@@ -221,7 +220,6 @@ impl Player {
|
||||
|
||||
async fn match_click_behaviour(
|
||||
&self,
|
||||
server: &Server,
|
||||
opened_container: Option<&mut Box<dyn Container>>,
|
||||
click: Click,
|
||||
drag_handler: &DragHandler,
|
||||
@@ -231,7 +229,6 @@ impl Player {
|
||||
match click.click_type {
|
||||
ClickType::MouseClick(mouse_click) => {
|
||||
self.mouse_click(
|
||||
server,
|
||||
opened_container,
|
||||
mouse_click,
|
||||
click.slot,
|
||||
@@ -288,7 +285,6 @@ impl Player {
|
||||
match drop_type {
|
||||
DropType::FullStack => {
|
||||
self.drop_item(
|
||||
server,
|
||||
item_stack.item.id,
|
||||
u32::from(item_stack.item_count),
|
||||
)
|
||||
@@ -296,7 +292,7 @@ impl Player {
|
||||
*slots[slot] = None;
|
||||
}
|
||||
DropType::SingleItem => {
|
||||
self.drop_item(server, item_stack.item.id, 1).await;
|
||||
self.drop_item(item_stack.item.id, 1).await;
|
||||
item_stack.item_count -= 1;
|
||||
if item_stack.item_count == 0 {
|
||||
*slots[slot] = None;
|
||||
@@ -312,7 +308,6 @@ impl Player {
|
||||
|
||||
async fn mouse_click(
|
||||
&self,
|
||||
server: &Server,
|
||||
opened_container: Option<&mut Box<dyn Container>>,
|
||||
mouse_click: MouseClick,
|
||||
slot: container_click::Slot,
|
||||
@@ -329,16 +324,12 @@ impl Player {
|
||||
if let Some(item_stack) = carried_item.as_mut() {
|
||||
match mouse_click {
|
||||
MouseClick::Left => {
|
||||
self.drop_item(
|
||||
server,
|
||||
item_stack.item.id,
|
||||
u32::from(item_stack.item_count),
|
||||
)
|
||||
.await;
|
||||
self.drop_item(item_stack.item.id, u32::from(item_stack.item_count))
|
||||
.await;
|
||||
*carried_item = None;
|
||||
}
|
||||
MouseClick::Right => {
|
||||
self.drop_item(server, item_stack.item.id, 1).await;
|
||||
self.drop_item(item_stack.item.id, 1).await;
|
||||
item_stack.item_count -= 1;
|
||||
if item_stack.item_count == 0 {
|
||||
*carried_item = None;
|
||||
|
||||
@@ -844,7 +844,7 @@ impl Player {
|
||||
// Block break & block break sound
|
||||
|
||||
world
|
||||
.break_block(server, &location, Some(self.clone()), false)
|
||||
.break_block(&location, Some(self.clone()), false)
|
||||
.await;
|
||||
if let Ok(block) = block {
|
||||
server
|
||||
@@ -863,9 +863,7 @@ impl Player {
|
||||
let speed = block::calc_block_breaking(&self, state, &block.name).await;
|
||||
// Instant break
|
||||
if speed >= 1.0 {
|
||||
world
|
||||
.break_block(server, &location, Some(self.clone()), true)
|
||||
.await;
|
||||
world.break_block(&location, Some(self.clone()), true).await;
|
||||
server
|
||||
.block_registry
|
||||
.broken(block, &self, location, server)
|
||||
@@ -924,9 +922,7 @@ impl Player {
|
||||
if let Ok(state) = state {
|
||||
let drop = self.gamemode.load() != GameMode::Creative
|
||||
&& self.can_harvest(state, &block.name).await;
|
||||
world
|
||||
.break_block(server, &location, Some(self.clone()), drop)
|
||||
.await;
|
||||
world.break_block(&location, Some(self.clone()), drop).await;
|
||||
}
|
||||
server
|
||||
.block_registry
|
||||
@@ -936,10 +932,10 @@ impl Player {
|
||||
self.update_sequence(player_action.sequence.0);
|
||||
}
|
||||
Status::DropItem => {
|
||||
self.drop_held_item(server, false).await;
|
||||
self.drop_held_item(false).await;
|
||||
}
|
||||
Status::DropItemStack => {
|
||||
self.drop_held_item(server, true).await;
|
||||
self.drop_held_item(true).await;
|
||||
}
|
||||
Status::ShootArrowOrFinishEating | Status::SwapItem => {
|
||||
log::debug!("todo");
|
||||
@@ -1079,8 +1075,7 @@ impl Player {
|
||||
}
|
||||
// check if item is a spawn egg
|
||||
if let Some(entity) = entity_from_egg(stack.item.id) {
|
||||
self.spawn_entity_from_egg(entity, server, location, &face)
|
||||
.await;
|
||||
self.spawn_entity_from_egg(entity, location, &face).await;
|
||||
should_try_decrement = true;
|
||||
};
|
||||
|
||||
@@ -1137,7 +1132,7 @@ impl Player {
|
||||
return;
|
||||
}
|
||||
if let Some(held) = self.inventory().lock().await.held_item() {
|
||||
server.item_registry.on_use(&held.item, self, server).await;
|
||||
server.item_registry.on_use(&held.item, self).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1157,7 +1152,6 @@ impl Player {
|
||||
|
||||
pub async fn handle_set_creative_slot(
|
||||
&self,
|
||||
server: &Server,
|
||||
packet: SSetCreativeSlot,
|
||||
) -> Result<(), InventoryError> {
|
||||
if self.gamemode.load() != GameMode::Creative {
|
||||
@@ -1173,7 +1167,7 @@ impl Player {
|
||||
.set_slot(packet.slot as usize, item_stack, true)?;
|
||||
} else if let Some(item_stack) = item_stack {
|
||||
// Item drop
|
||||
self.drop_item(server, item_stack.item.id, u32::from(item_stack.item_count))
|
||||
self.drop_item(item_stack.item.id, u32::from(item_stack.item_count))
|
||||
.await;
|
||||
};
|
||||
Ok(())
|
||||
@@ -1258,7 +1252,6 @@ impl Player {
|
||||
async fn spawn_entity_from_egg(
|
||||
&self,
|
||||
entity_type: EntityType,
|
||||
server: &Server,
|
||||
location: BlockPos,
|
||||
face: &BlockDirection,
|
||||
) {
|
||||
@@ -1274,13 +1267,7 @@ impl Player {
|
||||
|
||||
let world = self.world().await;
|
||||
// create new mob and uuid based on spawn egg id
|
||||
let mob = mob::from_type(
|
||||
EntityType::from_raw(entity_type.id).unwrap(),
|
||||
server,
|
||||
pos,
|
||||
&world,
|
||||
)
|
||||
.await;
|
||||
let mob = mob::from_type(EntityType::from_raw(entity_type.id).unwrap(), pos, &world).await;
|
||||
|
||||
// set the rotation
|
||||
mob.get_entity().set_rotation(yaw, 0.0);
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::block::properties::BlockPropertiesManager;
|
||||
use crate::block::registry::BlockRegistry;
|
||||
use crate::command::commands::default_dispatcher;
|
||||
use crate::command::commands::defaultgamemode::DefaultGamemode;
|
||||
use crate::entity::{Entity, EntityId};
|
||||
use crate::entity::EntityId;
|
||||
use crate::item::registry::ItemRegistry;
|
||||
use crate::net::EncryptionError;
|
||||
use crate::world::custom_bossbar::CustomBossbars;
|
||||
@@ -11,19 +11,15 @@ use crate::{
|
||||
command::dispatcher::CommandDispatcher, entity::player::Player, net::Client, world::World,
|
||||
};
|
||||
use connection_cache::{CachedBranding, CachedStatus};
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use key_store::KeyStore;
|
||||
use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG};
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_inventory::drag_handler::DragHandler;
|
||||
use pumpkin_inventory::{Container, OpenContainer};
|
||||
use pumpkin_protocol::client::login::CEncryptionRequest;
|
||||
use pumpkin_protocol::{ClientPacket, client::config::CPluginMessage};
|
||||
use pumpkin_registry::{DimensionType, Registry};
|
||||
use pumpkin_util::math::boundingbox::{BoundingBox, EntityDimensions};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::math::vector2::Vector2;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_world::block::registry::Block;
|
||||
use pumpkin_world::dimension::Dimension;
|
||||
@@ -32,10 +28,7 @@ use std::collections::HashMap;
|
||||
use std::net::IpAddr;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::{
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicI32, Ordering},
|
||||
},
|
||||
sync::{Arc, atomic::Ordering},
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
@@ -72,8 +65,6 @@ pub struct Server {
|
||||
// TODO: should have per player open_containers
|
||||
pub open_containers: RwLock<HashMap<u64, OpenContainer>>,
|
||||
pub drag_handler: DragHandler,
|
||||
/// Assigns unique IDs to entities.
|
||||
entity_id: AtomicI32,
|
||||
/// Assigns unique IDs to containers.
|
||||
container_id: AtomicU32,
|
||||
/// Manages authentication with a authentication server, if enabled.
|
||||
@@ -120,8 +111,6 @@ impl Server {
|
||||
cached_registry: Registry::get_synced(),
|
||||
open_containers: RwLock::new(HashMap::new()),
|
||||
drag_handler: DragHandler::new(),
|
||||
// 0 is invalid
|
||||
entity_id: 2.into(),
|
||||
container_id: 0.into(),
|
||||
worlds: RwLock::new(vec![Arc::new(world)]),
|
||||
dimensions: vec![
|
||||
@@ -179,13 +168,12 @@ impl Server {
|
||||
///
|
||||
/// You still have to spawn the Player in the World to make then to let them Join and make them Visible
|
||||
pub async fn add_player(&self, client: Arc<Client>) -> (Arc<Player>, Arc<World>) {
|
||||
let entity_id = self.new_entity_id();
|
||||
let gamemode = self.defaultgamemode.lock().await.gamemode;
|
||||
// Basically the default world
|
||||
// TODO: select default from config
|
||||
let world = &self.worlds.read().await[0];
|
||||
|
||||
let player = Arc::new(Player::new(client, world.clone(), entity_id, gamemode).await);
|
||||
let player = Arc::new(Player::new(client, world.clone(), gamemode).await);
|
||||
world
|
||||
.add_player(player.gameprofile.id, player.clone())
|
||||
.await;
|
||||
@@ -213,49 +201,6 @@ impl Server {
|
||||
log::info!("Completed world save");
|
||||
}
|
||||
|
||||
/// Adds a new living entity to the server. This does not Spawn the entity
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A tuple containing:
|
||||
///
|
||||
/// - `Arc<LivingEntity>`: A reference to the newly created living entity.
|
||||
/// - `Arc<World>`: A reference to the world that the living entity was added to.
|
||||
/// - `Uuid`: The uuid of the newly created living entity to be used to send to the client.
|
||||
pub fn add_entity(
|
||||
&self,
|
||||
position: Vector3<f64>,
|
||||
entity_type: EntityType,
|
||||
world: &Arc<World>,
|
||||
) -> Entity {
|
||||
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 = EntityDimensions {
|
||||
width: entity_type.dimension[0],
|
||||
height: entity_type.dimension[1],
|
||||
};
|
||||
|
||||
// TODO: standing eye height should be per mob
|
||||
let new_uuid = uuid::Uuid::new_v4();
|
||||
Entity::new(
|
||||
entity_id,
|
||||
new_uuid,
|
||||
world.clone(),
|
||||
position,
|
||||
entity_type,
|
||||
entity_type.eye_height,
|
||||
AtomicCell::new(BoundingBox::new_from_pos(
|
||||
position.x,
|
||||
position.y,
|
||||
position.z,
|
||||
&bounding_box_size,
|
||||
)),
|
||||
AtomicCell::new(bounding_box_size),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn try_get_container(
|
||||
&self,
|
||||
player_id: EntityId,
|
||||
@@ -446,12 +391,6 @@ impl Server {
|
||||
false
|
||||
}
|
||||
|
||||
/// Generates a new entity id
|
||||
/// This should be global
|
||||
pub fn new_entity_id(&self) -> EntityId {
|
||||
self.entity_id.fetch_add(1, Ordering::SeqCst)
|
||||
}
|
||||
|
||||
/// Generates a new container id
|
||||
pub fn new_container_id(&self) -> u32 {
|
||||
self.container_id.fetch_add(1, Ordering::SeqCst)
|
||||
|
||||
@@ -82,10 +82,10 @@ impl Explosion {
|
||||
let block = world.get_block(&pos).await.unwrap();
|
||||
let pumpkin_block = server.block_registry.get_pumpkin_block(block);
|
||||
if pumpkin_block.is_none_or(|s| s.should_drop_items_on_explosion()) {
|
||||
drop_loot(server, world, block, &pos, false).await;
|
||||
drop_loot(world, block, &pos, false).await;
|
||||
}
|
||||
if let Some(pumpkin_block) = pumpkin_block {
|
||||
pumpkin_block.explode(block, world, pos, server).await;
|
||||
pumpkin_block.explode(block, world, pos).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1003,6 +1003,15 @@ impl World {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_entity(
|
||||
self: &Arc<Self>,
|
||||
position: Vector3<f64>,
|
||||
entity_type: EntityType,
|
||||
) -> Entity {
|
||||
let uuid = uuid::Uuid::new_v4();
|
||||
Entity::new(uuid, self.clone(), position, entity_type, false)
|
||||
}
|
||||
|
||||
/// Adds a entity to the world.
|
||||
pub async fn spawn_entity(&self, entity: Arc<dyn EntityBase>) {
|
||||
let base_entity = entity.get_entity();
|
||||
@@ -1087,7 +1096,6 @@ impl World {
|
||||
|
||||
pub async fn break_block(
|
||||
self: &Arc<Self>,
|
||||
server: &Server,
|
||||
position: &BlockPos,
|
||||
cause: Option<Arc<Player>>,
|
||||
drop: bool,
|
||||
@@ -1112,7 +1120,7 @@ impl World {
|
||||
);
|
||||
|
||||
if drop {
|
||||
block::drop_loot(server, self, block, position, true).await;
|
||||
block::drop_loot(self, block, position, true).await;
|
||||
}
|
||||
|
||||
match cause {
|
||||
|
||||
Reference in New Issue
Block a user