Add Clientbound Entity Status
This commit is contained in:
parent
a60980508e
commit
f9bf750b65
18
pumpkin-protocol/src/client/play/c_entity_status.rs
Normal file
18
pumpkin-protocol/src/client/play/c_entity_status.rs
Normal file
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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::*;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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> {
|
||||
@ -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> {
|
||||
|
||||
@ -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!(
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
@ -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) {
|
||||
|
||||
@ -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())?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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,
|
||||
@ -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;
|
||||
@ -258,13 +260,9 @@ 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());
|
||||
}
|
||||
@ -272,6 +270,16 @@ impl World {
|
||||
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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user