Skip to content

Commit

Permalink
Add Clientbound Entity Status
Browse files Browse the repository at this point in the history
  • Loading branch information
Snowiiii committed Sep 12, 2024
1 parent a609805 commit f9bf750
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 23 deletions.
18 changes: 18 additions & 0 deletions pumpkin-protocol/src/client/play/c_entity_status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use pumpkin_macros::packet;
use serde::Serialize;

#[derive(Serialize)]
#[packet(0x1F)]
pub struct CEntityStatus {
entity_id: i32,
entity_status: i8,
}

impl CEntityStatus {
pub fn new(entity_id: i32, entity_status: i8) -> Self {
Self {
entity_id,
entity_status,
}
}
}
26 changes: 24 additions & 2 deletions pumpkin-protocol/src/client/play/c_game_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,30 @@ pub struct CGameEvent {
value: f32,
}

/// Somewhere you need to implement all the random stuff right?
impl CGameEvent {
pub fn new(event: u8, value: f32) -> Self {
Self { event, value }
pub fn new(event: GameEvent, value: f32) -> Self {
Self {
event: event as u8,
value,
}
}
}

#[repr(u8)]
pub enum GameEvent {
NoRespawnBlockAvailable,
BeginRaining,
EndRaining,
ChangeGameMode,
WinGame,
DemoEvent,
ArrowHitPlayer,
RainLevelChange,
ThunderLevelChange,
PlayPufferfishStringSound,
PlayElderGuardianMobAppearance,
EnabledRespawnScreen,
LimitedCrafting,
StartWaitingChunks,
}
2 changes: 2 additions & 0 deletions pumpkin-protocol/src/client/play/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod c_close_container;
mod c_disguised_chat_message;
mod c_entity_animation;
mod c_entity_metadata;
mod c_entity_status;
mod c_entity_velocity;
mod c_game_event;
mod c_head_rot;
Expand Down Expand Up @@ -51,6 +52,7 @@ pub use c_close_container::*;
pub use c_disguised_chat_message::*;
pub use c_entity_animation::*;
pub use c_entity_metadata::*;
pub use c_entity_status::*;
pub use c_entity_velocity::*;
pub use c_game_event::*;
pub use c_head_rot::*;
Expand Down
2 changes: 1 addition & 1 deletion pumpkin/src/client/player_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ impl Player {
let config = &ADVANCED_CONFIG.pvp;
if config.enabled {
let world = &entity.world;
let attacked_player = world.get_by_entityid(self, entity_id.0 as EntityId);
let attacked_player = world.get_player_by_entityid(entity_id.0 as EntityId);
if let Some(player) = attacked_player {
let victem_entity = &player.entity;
if config.protect_creative
Expand Down
4 changes: 4 additions & 0 deletions pumpkin/src/commands/arg_player.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::sync::Arc;

use crate::commands::dispatcher::InvalidTreeError;
use crate::commands::dispatcher::InvalidTreeError::InvalidConsumptionError;
use crate::commands::tree::{ConsumedArgs, RawArgs};
use crate::commands::CommandSender;
use crate::commands::CommandSender::Player;
use crate::server::Server;

/// todo: implement (so far only own name + @s/@p is implemented)
pub fn consume_arg_player(src: &CommandSender, args: &mut RawArgs) -> Option<String> {
Expand All @@ -29,6 +32,7 @@ pub fn consume_arg_player(src: &CommandSender, args: &mut RawArgs) -> Option<Str
/// todo: implement (so far only own name + @s/@p is implemented)
pub fn parse_arg_player<'a>(
src: &'a mut CommandSender,
_server: &Arc<Server>,
arg_name: &str,
consumed_args: &ConsumedArgs,
) -> Result<&'a crate::entity::player::Player, InvalidTreeError> {
Expand Down
4 changes: 2 additions & 2 deletions pumpkin/src/commands/cmd_gamemode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
}),
)
.with_child(argument(ARG_TARGET, consume_arg_player).execute(
&|sender, _, args| {
&|sender, server, args| {
let gamemode = parse_arg_gamemode(args)?;
let target = parse_arg_player(sender, ARG_TARGET, args)?;
let target = parse_arg_player(sender, server, ARG_TARGET, args)?;

if target.gamemode.load() == gamemode {
target.send_system_message(TextComponent::text(&format!(
Expand Down
17 changes: 15 additions & 2 deletions pumpkin/src/entity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use pumpkin_core::math::{
};
use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, EntityId};
use pumpkin_protocol::{
client::play::{CSetEntityMetadata, Metadata},
client::play::{CEntityStatus, CSetEntityMetadata, Metadata},
VarInt,
};

Expand Down Expand Up @@ -121,8 +121,21 @@ impl Entity {
self.pitch.store(pitch);
}

/// Kills the Entity
///
/// This is simliar to `kill` but Spawn Particles, Animation and plays death sound
pub fn kill(&self) {
// Spawns death smoke particles
self.world
.broadcast_packet_all(&CEntityStatus::new(self.entity_id, 60));
// Plays the death sound and death animation
self.world
.broadcast_packet_all(&CEntityStatus::new(self.entity_id, 3));
self.remove();
}

/// Removes the Entity from their current World
pub async fn remove(&mut self) {
pub fn remove(&self) {
self.world.remove_entity(self);
}

Expand Down
8 changes: 5 additions & 3 deletions pumpkin/src/entity/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use pumpkin_protocol::{
bytebuf::{packet_id::Packet, DeserializerError},
client::play::{
CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSyncPlayerPosition,
CSystemChatMessage, PlayerAction,
CSystemChatMessage, GameEvent, PlayerAction,
},
server::play::{
SChatCommand, SChatMessage, SClickContainer, SClientInformationPlay, SConfirmTeleport,
Expand Down Expand Up @@ -248,8 +248,10 @@ impl Player {
actions: vec![PlayerAction::UpdateGameMode((gamemode as i32).into())],
}],
));
self.client
.send_packet(&CGameEvent::new(3, gamemode.to_f32().unwrap()));
self.client.send_packet(&CGameEvent::new(
GameEvent::ChangeGameMode,
gamemode.to_f32().unwrap(),
));
}

pub fn send_system_message(&self, text: TextComponent) {
Expand Down
3 changes: 0 additions & 3 deletions pumpkin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,7 @@ fn main() -> io::Result<()> {
if closed {
if let Some(player) = players.remove(&token) {
player.remove().await;
dbg!("b");
let connection = &mut player.client.connection.lock();
dbg!("c");

poll.registry().deregister(connection.by_ref())?;
}
}
Expand Down
10 changes: 10 additions & 0 deletions pumpkin/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ impl Server {
}
}

/// Searches every world for a player by name
pub fn get_player_by_name(&self, name: &str) -> Option<Arc<Player>> {
for world in self.worlds.iter() {
if let Some(player) = world.get_player_by_name(name) {
return Some(player);
}
}
None
}

/// Generates a new entity id
/// This should be global
pub fn new_entity_id(&self) -> EntityId {
Expand Down
28 changes: 18 additions & 10 deletions pumpkin/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_protocol::{
client::play::{
CChunkData, CGameEvent, CLogin, CPlayerAbilities, CPlayerInfoUpdate, CRemoveEntities,
CRemovePlayerInfo, CSetEntityMetadata, CSpawnEntity, Metadata, PlayerAction,
CRemovePlayerInfo, CSetEntityMetadata, CSpawnEntity, GameEvent, Metadata, PlayerAction,
},
uuid::UUID,
ClientPacket, VarInt,
Expand Down Expand Up @@ -216,8 +216,10 @@ impl World {
self.broadcast_packet_all(&packet)
}

// Start waiting for level chunks
player.client.send_packet(&CGameEvent::new(13, 0.0));
// Start waiting for level chunks, Sets the "Loading Terrain" screen
player
.client
.send_packet(&CGameEvent::new(GameEvent::StartWaitingChunks, 0.0));

// Spawn in inital chunks
player_chunker::player_join(self, player.clone()).await;
Expand Down Expand Up @@ -258,20 +260,26 @@ impl World {
dbg!("DONE CHUNKS", inst.elapsed());
}

pub fn get_by_entityid(&self, from: &Player, id: EntityId) -> Option<Arc<Player>> {
for (_, player) in self
.current_players
.lock()
.iter()
.filter(|c| c.0 != &from.client.token)
{
/// Gets a Player by entity id
pub fn get_player_by_entityid(&self, id: EntityId) -> Option<Arc<Player>> {
for (_, player) in self.current_players.lock().iter() {
if player.entity_id() == id {
return Some(player.clone());
}
}
None
}

/// Gets a Player by name
pub fn get_player_by_name(&self, name: &str) -> Option<Arc<Player>> {
for (_, player) in self.current_players.lock().iter() {
if player.gameprofile.name == name {
return Some(player.clone());
}
}
None
}

pub fn add_player(&self, token: Token, player: Arc<Player>) {
self.current_players.lock().insert(token, player);
}
Expand Down

0 comments on commit f9bf750

Please sign in to comment.