Some more Item dropping work
And also some fixes
This commit is contained in:
parent
ef497fb435
commit
819e0c62ac
@ -1,6 +1,6 @@
|
||||
use super::{position::BlockPos, vector3::Vector3};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct BoundingBox {
|
||||
pub min: Vector3<f64>,
|
||||
pub max: Vector3<f64>,
|
||||
@ -74,7 +74,7 @@ impl BoundingBox {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct BoundingBoxSize {
|
||||
pub width: f64,
|
||||
pub height: f64,
|
||||
|
||||
@ -58,7 +58,7 @@ pub enum Direction {
|
||||
West,
|
||||
}
|
||||
|
||||
// TODO: We can automaticly parse them ig
|
||||
// TODO: We can automatically parse them ig
|
||||
#[must_use]
|
||||
pub fn get_property_key(property_name: &str) -> Option<BlockProperty> {
|
||||
match property_name {
|
||||
@ -93,7 +93,6 @@ pub fn evaluate_layers(
|
||||
}
|
||||
|
||||
if block.id == clicked_block.id {
|
||||
dbg!(property);
|
||||
// bro its is so hacky :crying:
|
||||
let mut layer: u8 = property.replace("layers", "").parse().unwrap();
|
||||
// lets add a new layer
|
||||
|
||||
@ -32,7 +32,6 @@ impl ArgumentConsumer for TextComponentArgConsumer {
|
||||
let text_component = parse_text_component(s);
|
||||
|
||||
let Some(text_component) = text_component else {
|
||||
dbg!(text_component);
|
||||
if s.starts_with('"') && s.ends_with('"') {
|
||||
let s = s.replace('"', "");
|
||||
return Some(Arg::TextComponent(TextComponent::text(s)));
|
||||
|
||||
@ -37,8 +37,8 @@ impl CommandExecutor for SummonExecutor {
|
||||
// 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, uuid) = mob::from_type(entity, server, pos, player.world()).await;
|
||||
player.world().spawn_entity(uuid, mob).await;
|
||||
let mob = mob::from_type(entity, server, pos, player.world()).await;
|
||||
player.world().spawn_entity(mob).await;
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.summon.success",
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::sync::atomic::AtomicI8;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_protocol::{
|
||||
client::play::{MetaDataType, Metadata},
|
||||
@ -10,12 +12,17 @@ use super::{living::LivingEntity, Entity, EntityBase};
|
||||
pub struct ItemEntity {
|
||||
entity: Entity,
|
||||
item: Slot,
|
||||
pickup_delay: AtomicI8,
|
||||
}
|
||||
|
||||
impl ItemEntity {
|
||||
pub fn new(entity: Entity, stack: &ItemStack) -> Self {
|
||||
let slot = Slot::from(stack);
|
||||
Self { entity, item: slot }
|
||||
Self {
|
||||
entity,
|
||||
item: slot,
|
||||
pickup_delay: AtomicI8::new(10), // Vanilla
|
||||
}
|
||||
}
|
||||
pub async fn send_meta_packet(&self) {
|
||||
self.entity
|
||||
@ -26,7 +33,18 @@ impl ItemEntity {
|
||||
|
||||
#[async_trait]
|
||||
impl EntityBase for ItemEntity {
|
||||
async fn tick(&self) {}
|
||||
async fn tick(&self) {
|
||||
if self.pickup_delay.load(std::sync::atomic::Ordering::Relaxed) >= 0 {
|
||||
self.pickup_delay
|
||||
.fetch_sub(1, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
async fn on_player_collision(&self) {
|
||||
if self.pickup_delay.load(std::sync::atomic::Ordering::Relaxed) == 0 {
|
||||
// check if inventory is full
|
||||
self.entity.remove().await;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_entity(&self) -> &Entity {
|
||||
&self.entity
|
||||
|
||||
@ -4,7 +4,6 @@ use async_trait::async_trait;
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use tokio::sync::Mutex;
|
||||
use uuid::Uuid;
|
||||
use zombie::Zombie;
|
||||
|
||||
use crate::{server::Server, world::World};
|
||||
@ -56,8 +55,8 @@ pub async fn from_type(
|
||||
server: &Server,
|
||||
position: Vector3<f64>,
|
||||
world: &Arc<World>,
|
||||
) -> (Arc<dyn EntityBase>, Uuid) {
|
||||
let (entity, uuid) = server.add_entity(position, entity_type, world);
|
||||
) -> Arc<dyn EntityBase> {
|
||||
let entity = server.add_entity(position, entity_type, world);
|
||||
let mob = MobEntity {
|
||||
living_entity: LivingEntity::new(entity),
|
||||
goals: Mutex::new(vec![]),
|
||||
@ -69,7 +68,7 @@ pub async fn from_type(
|
||||
// TODO
|
||||
_ => (),
|
||||
}
|
||||
(Arc::new(mob), uuid)
|
||||
Arc::new(mob)
|
||||
}
|
||||
|
||||
impl MobEntity {
|
||||
|
||||
@ -25,7 +25,6 @@ use pumpkin_util::math::{
|
||||
wrap_degrees,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::world::World;
|
||||
|
||||
@ -39,7 +38,10 @@ pub type EntityId = i32;
|
||||
|
||||
#[async_trait]
|
||||
pub trait EntityBase: Send + Sync {
|
||||
async fn tick(&self);
|
||||
/// Gets Called every tick
|
||||
async fn tick(&self) {}
|
||||
/// Called when a player collides with the entity
|
||||
async fn on_player_collision(&self) {}
|
||||
fn get_entity(&self) -> &Entity;
|
||||
fn get_living_entity(&self) -> Option<&LivingEntity>;
|
||||
}
|
||||
@ -222,12 +224,12 @@ impl Entity {
|
||||
self.world.remove_entity(self).await;
|
||||
}
|
||||
|
||||
pub fn create_spawn_packet(&self, uuid: Uuid) -> CSpawnEntity {
|
||||
pub fn create_spawn_packet(&self) -> CSpawnEntity {
|
||||
let entity_loc = self.pos.load();
|
||||
let entity_vel = self.velocity.load();
|
||||
CSpawnEntity::new(
|
||||
VarInt(self.entity_id),
|
||||
uuid,
|
||||
self.entity_uuid,
|
||||
VarInt((self.entity_type) as i32),
|
||||
entity_loc.x,
|
||||
entity_loc.y,
|
||||
@ -328,7 +330,7 @@ impl Entity {
|
||||
pub async fn set_pose(&self, pose: EntityPose) {
|
||||
self.pose.store(pose);
|
||||
let pose = pose as i32;
|
||||
self.send_meta_data(Metadata::new(6, MetaDataType::EntityPose, pose))
|
||||
self.send_meta_data(Metadata::new(6, MetaDataType::EntityPose, VarInt(pose)))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,9 +537,9 @@ impl Player {
|
||||
// TODO: This should be optimized for larger servers based on current player chunk
|
||||
pub async fn send_mobs(&self, world: &World) {
|
||||
let entities = world.entities.lock().await.clone();
|
||||
for (uuid, entity) in entities {
|
||||
for (_, entity) in entities {
|
||||
self.client
|
||||
.send_packet(&entity.get_entity().create_spawn_packet(uuid))
|
||||
.send_packet(&entity.get_entity().create_spawn_packet())
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@ -718,13 +718,13 @@ impl Player {
|
||||
pub async fn drop_item(&self, server: &Server) {
|
||||
let inv = self.inventory.lock().await;
|
||||
if let Some(item) = inv.held_item() {
|
||||
let (entity, uuid) = server.add_entity(
|
||||
let entity = server.add_entity(
|
||||
self.living_entity.entity.pos.load(),
|
||||
EntityType::Item,
|
||||
self.world(),
|
||||
);
|
||||
let item_entity = Arc::new(ItemEntity::new(entity, item));
|
||||
self.world().spawn_entity(uuid, item_entity.clone()).await;
|
||||
self.world().spawn_entity(item_entity.clone()).await;
|
||||
item_entity.send_meta_packet().await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1125,7 +1125,7 @@ impl Player {
|
||||
|
||||
let world = self.world();
|
||||
// create new mob and uuid based on spawn egg id
|
||||
let (mob, uuid) = mob::from_type(
|
||||
let mob = mob::from_type(
|
||||
EntityType::from_raw(*spawn_item_id).unwrap(),
|
||||
server,
|
||||
pos,
|
||||
@ -1137,7 +1137,7 @@ impl Player {
|
||||
mob.get_entity().set_rotation(yaw, 0.0);
|
||||
|
||||
// broadcast new mob to all players
|
||||
world.spawn_entity(uuid, mob).await;
|
||||
world.spawn_entity(mob).await;
|
||||
|
||||
// TODO: send/configure additional commands/data based on type of entity (horse, slime, etc)
|
||||
} else {
|
||||
|
||||
@ -29,7 +29,6 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::block::block_manager::BlockManager;
|
||||
use crate::block::properties::BlockPropertiesManager;
|
||||
@ -218,7 +217,7 @@ impl Server {
|
||||
position: Vector3<f64>,
|
||||
entity_type: EntityType,
|
||||
world: &Arc<World>,
|
||||
) -> (Entity, Uuid) {
|
||||
) -> Entity {
|
||||
let entity_id = self.new_entity_id();
|
||||
|
||||
// TODO: this should be resolved to a integer using a macro when calling this function
|
||||
@ -235,18 +234,21 @@ impl Server {
|
||||
|
||||
// TODO: standing eye height should be per mob
|
||||
let new_uuid = uuid::Uuid::new_v4();
|
||||
let entity = Entity::new(
|
||||
Entity::new(
|
||||
entity_id,
|
||||
new_uuid,
|
||||
world.clone(),
|
||||
position,
|
||||
entity_type,
|
||||
1.62,
|
||||
AtomicCell::new(BoundingBox::new_default(&bounding_box_size)),
|
||||
AtomicCell::new(BoundingBox::new_from_pos(
|
||||
position.x,
|
||||
position.y,
|
||||
position.z,
|
||||
&bounding_box_size,
|
||||
)),
|
||||
AtomicCell::new(bounding_box_size),
|
||||
);
|
||||
|
||||
(entity, new_uuid)
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn try_get_container(
|
||||
|
||||
@ -234,9 +234,27 @@ impl World {
|
||||
for player in self.players.lock().await.values() {
|
||||
player.tick().await;
|
||||
}
|
||||
|
||||
// entities tick
|
||||
for entity in self.entities.lock().await.values() {
|
||||
entity.tick().await;
|
||||
// this boolean thing prevents deadlocks, since we lock players we can't broadcast packets
|
||||
let mut collied = false;
|
||||
for player in self.players.lock().await.values() {
|
||||
if player
|
||||
.living_entity
|
||||
.entity
|
||||
.bounding_box
|
||||
.load()
|
||||
.intersects(&entity.get_entity().bounding_box.load())
|
||||
{
|
||||
collied = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if collied {
|
||||
entity.on_player_collision().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -838,11 +856,12 @@ impl World {
|
||||
///
|
||||
/// * `uuid`: The unique UUID of the living entity to add.
|
||||
/// * `living_entity`: A `Arc<LivingEntity>` reference to the living entity object.
|
||||
pub async fn spawn_entity(&self, uuid: uuid::Uuid, entity: Arc<dyn EntityBase>) {
|
||||
self.broadcast_packet_all(&entity.get_entity().create_spawn_packet(uuid))
|
||||
pub async fn spawn_entity(&self, entity: Arc<dyn EntityBase>) {
|
||||
let base_entity = entity.get_entity();
|
||||
self.broadcast_packet_all(&base_entity.create_spawn_packet())
|
||||
.await;
|
||||
let mut current_living_entities = self.entities.lock().await;
|
||||
current_living_entities.insert(uuid, entity);
|
||||
current_living_entities.insert(base_entity.entity_uuid, entity);
|
||||
}
|
||||
|
||||
pub async fn remove_entity(&self, entity: &Entity) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user