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