mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-31 20:32:34 +00:00
Add Mobs to Login Sequence (#488)
* Added mobs to login sequence * Fix naming and add inital velocity
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_protocol::{client::play::CSpawnEntity, codec::var_int::VarInt};
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use tokio::sync::Mutex;
|
||||
use uuid::Uuid;
|
||||
@@ -60,4 +61,25 @@ impl MobEntity {
|
||||
pub async fn goal<T: Goal + 'static>(&self, goal: T) {
|
||||
self.goals.lock().await.push((Arc::new(goal), false));
|
||||
}
|
||||
|
||||
pub fn create_spawn_entity_packet(&self, uuid: Uuid) -> CSpawnEntity {
|
||||
let e = &self.living_entity.entity;
|
||||
let entity_loc = e.pos.load();
|
||||
let entity_vel = e.velocity.load();
|
||||
CSpawnEntity::new(
|
||||
VarInt(e.entity_id),
|
||||
uuid,
|
||||
VarInt((e.entity_type) as i32),
|
||||
entity_loc.x,
|
||||
entity_loc.y,
|
||||
entity_loc.z,
|
||||
e.pitch.load(),
|
||||
e.yaw.load(),
|
||||
e.yaw.load(), // todo: head_yaw and yaw are swapped, find out why
|
||||
0.into(),
|
||||
entity_vel.x as f32,
|
||||
entity_vel.y as f32,
|
||||
entity_vel.z as f32,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,6 +532,17 @@ impl Player {
|
||||
.await;
|
||||
}
|
||||
|
||||
/// Sends the mobs to just the player.
|
||||
// TODO: This should be optimized for larger servers based on current player chunk
|
||||
pub async fn send_mobs(&self, world: &World) {
|
||||
let mobs = world.current_living_mobs.lock().await.clone();
|
||||
for (uuid, mob) in mobs {
|
||||
self.client
|
||||
.send_packet(&mob.create_spawn_entity_packet(uuid))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Yaw and Pitch in degrees
|
||||
/// Rarly used, For example when waking up player from bed or first time spawn. Otherwise entity teleport is used
|
||||
/// Player should respond with the `SConfirmTeleport` packet
|
||||
|
||||
@@ -16,7 +16,7 @@ use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_data::world::CHAT;
|
||||
use pumpkin_inventory::player::PlayerInventory;
|
||||
use pumpkin_inventory::InventoryError;
|
||||
use pumpkin_protocol::client::play::{CSetContainerSlot, CSetHeldItem, CSpawnEntity};
|
||||
use pumpkin_protocol::client::play::{CSetContainerSlot, CSetHeldItem};
|
||||
use pumpkin_protocol::codec::slot::Slot;
|
||||
use pumpkin_protocol::codec::var_int::VarInt;
|
||||
use pumpkin_protocol::server::play::SCookieResponse as SPCookieResponse;
|
||||
@@ -1092,8 +1092,10 @@ impl Player {
|
||||
f64::from(world_pos.0.y),
|
||||
f64::from(world_pos.0.z) + 0.5,
|
||||
);
|
||||
// create rotation like Vanilla
|
||||
let yaw = wrap_degrees(rand::random::<f32>() * 360.0) % 360.0;
|
||||
|
||||
// TODO: this should not be hardcoded
|
||||
// create new mob and uuid based on spawn egg id
|
||||
let (mob, uuid) = mob::from_type(
|
||||
EntityType::from_raw(*spawn_item_id).unwrap(),
|
||||
server,
|
||||
@@ -1101,25 +1103,13 @@ impl Player {
|
||||
self.world(),
|
||||
)
|
||||
.await;
|
||||
let yaw = wrap_degrees(rand::random::<f32>() * 360.0) % 360.0;
|
||||
|
||||
// set the rotation
|
||||
mob.living_entity.entity.set_rotation(yaw, 0.0);
|
||||
|
||||
// broadcast new mob to all players
|
||||
server
|
||||
.broadcast_packet_all(&CSpawnEntity::new(
|
||||
VarInt(mob.living_entity.entity.entity_id),
|
||||
uuid,
|
||||
VarInt((*spawn_item_id).into()),
|
||||
pos.x,
|
||||
pos.y,
|
||||
pos.z,
|
||||
0.0,
|
||||
yaw,
|
||||
yaw,
|
||||
0.into(),
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
))
|
||||
.broadcast_packet_all(&mob.create_spawn_entity_packet(uuid))
|
||||
.await;
|
||||
|
||||
// TODO: send/configure additional commands/data based on type of entity (horse, slime, etc)
|
||||
|
||||
@@ -462,6 +462,8 @@ impl World {
|
||||
// player.send_bossbar(bossbar).await;
|
||||
// }
|
||||
// }
|
||||
|
||||
player.send_mobs(self).await;
|
||||
}
|
||||
|
||||
pub async fn respawn_player(&self, player: &Arc<Player>, alive: bool) {
|
||||
@@ -865,13 +867,18 @@ impl World {
|
||||
}
|
||||
|
||||
pub async fn remove_mob_entity(self: Arc<Self>, living_entity: Arc<LivingEntity>) {
|
||||
let mut current_living_entities = self.current_living_mobs.lock().await.clone();
|
||||
current_living_entities.remove(&living_entity.entity.entity_uuid);
|
||||
let mut current_living_entities = self.current_living_mobs.lock().await;
|
||||
current_living_entities
|
||||
.remove(&living_entity.entity.entity_uuid)
|
||||
.unwrap();
|
||||
|
||||
// TODO: does this work with collisions?
|
||||
living_entity.entity.set_pose(EntityPose::Dying).await;
|
||||
|
||||
let world = self.clone();
|
||||
tokio::spawn(async move {
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(2000)).await;
|
||||
self.remove_entity(&living_entity.entity).await;
|
||||
world.remove_entity(&living_entity.entity).await;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user