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,
|
value: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Somewhere you need to implement all the random stuff right?
|
||||||
impl CGameEvent {
|
impl CGameEvent {
|
||||||
pub fn new(event: u8, value: f32) -> Self {
|
pub fn new(event: GameEvent, value: f32) -> Self {
|
||||||
Self { event, value }
|
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_disguised_chat_message;
|
||||||
mod c_entity_animation;
|
mod c_entity_animation;
|
||||||
mod c_entity_metadata;
|
mod c_entity_metadata;
|
||||||
|
mod c_entity_status;
|
||||||
mod c_entity_velocity;
|
mod c_entity_velocity;
|
||||||
mod c_game_event;
|
mod c_game_event;
|
||||||
mod c_head_rot;
|
mod c_head_rot;
|
||||||
@ -51,6 +52,7 @@ pub use c_close_container::*;
|
|||||||
pub use c_disguised_chat_message::*;
|
pub use c_disguised_chat_message::*;
|
||||||
pub use c_entity_animation::*;
|
pub use c_entity_animation::*;
|
||||||
pub use c_entity_metadata::*;
|
pub use c_entity_metadata::*;
|
||||||
|
pub use c_entity_status::*;
|
||||||
pub use c_entity_velocity::*;
|
pub use c_entity_velocity::*;
|
||||||
pub use c_game_event::*;
|
pub use c_game_event::*;
|
||||||
pub use c_head_rot::*;
|
pub use c_head_rot::*;
|
||||||
|
|||||||
@ -379,7 +379,7 @@ impl Player {
|
|||||||
let config = &ADVANCED_CONFIG.pvp;
|
let config = &ADVANCED_CONFIG.pvp;
|
||||||
if config.enabled {
|
if config.enabled {
|
||||||
let world = &entity.world;
|
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 {
|
if let Some(player) = attacked_player {
|
||||||
let victem_entity = &player.entity;
|
let victem_entity = &player.entity;
|
||||||
if config.protect_creative
|
if config.protect_creative
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::commands::dispatcher::InvalidTreeError;
|
use crate::commands::dispatcher::InvalidTreeError;
|
||||||
use crate::commands::dispatcher::InvalidTreeError::InvalidConsumptionError;
|
use crate::commands::dispatcher::InvalidTreeError::InvalidConsumptionError;
|
||||||
use crate::commands::tree::{ConsumedArgs, RawArgs};
|
use crate::commands::tree::{ConsumedArgs, RawArgs};
|
||||||
use crate::commands::CommandSender;
|
use crate::commands::CommandSender;
|
||||||
use crate::commands::CommandSender::Player;
|
use crate::commands::CommandSender::Player;
|
||||||
|
use crate::server::Server;
|
||||||
|
|
||||||
/// todo: implement (so far only own name + @s/@p is implemented)
|
/// todo: implement (so far only own name + @s/@p is implemented)
|
||||||
pub fn consume_arg_player(src: &CommandSender, args: &mut RawArgs) -> Option<String> {
|
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)
|
/// todo: implement (so far only own name + @s/@p is implemented)
|
||||||
pub fn parse_arg_player<'a>(
|
pub fn parse_arg_player<'a>(
|
||||||
src: &'a mut CommandSender,
|
src: &'a mut CommandSender,
|
||||||
|
_server: &Arc<Server>,
|
||||||
arg_name: &str,
|
arg_name: &str,
|
||||||
consumed_args: &ConsumedArgs,
|
consumed_args: &ConsumedArgs,
|
||||||
) -> Result<&'a crate::entity::player::Player, InvalidTreeError> {
|
) -> 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(
|
.with_child(argument(ARG_TARGET, consume_arg_player).execute(
|
||||||
&|sender, _, args| {
|
&|sender, server, args| {
|
||||||
let gamemode = parse_arg_gamemode(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 {
|
if target.gamemode.load() == gamemode {
|
||||||
target.send_system_message(TextComponent::text(&format!(
|
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_entity::{entity_type::EntityType, pose::EntityPose, EntityId};
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
client::play::{CSetEntityMetadata, Metadata},
|
client::play::{CEntityStatus, CSetEntityMetadata, Metadata},
|
||||||
VarInt,
|
VarInt,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,8 +121,21 @@ impl Entity {
|
|||||||
self.pitch.store(pitch);
|
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
|
/// Removes the Entity from their current World
|
||||||
pub async fn remove(&mut self) {
|
pub fn remove(&self) {
|
||||||
self.world.remove_entity(self);
|
self.world.remove_entity(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ use pumpkin_protocol::{
|
|||||||
bytebuf::{packet_id::Packet, DeserializerError},
|
bytebuf::{packet_id::Packet, DeserializerError},
|
||||||
client::play::{
|
client::play::{
|
||||||
CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSyncPlayerPosition,
|
CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSyncPlayerPosition,
|
||||||
CSystemChatMessage, PlayerAction,
|
CSystemChatMessage, GameEvent, PlayerAction,
|
||||||
},
|
},
|
||||||
server::play::{
|
server::play::{
|
||||||
SChatCommand, SChatMessage, SClickContainer, SClientInformationPlay, SConfirmTeleport,
|
SChatCommand, SChatMessage, SClickContainer, SClientInformationPlay, SConfirmTeleport,
|
||||||
@ -248,8 +248,10 @@ impl Player {
|
|||||||
actions: vec![PlayerAction::UpdateGameMode((gamemode as i32).into())],
|
actions: vec![PlayerAction::UpdateGameMode((gamemode as i32).into())],
|
||||||
}],
|
}],
|
||||||
));
|
));
|
||||||
self.client
|
self.client.send_packet(&CGameEvent::new(
|
||||||
.send_packet(&CGameEvent::new(3, gamemode.to_f32().unwrap()));
|
GameEvent::ChangeGameMode,
|
||||||
|
gamemode.to_f32().unwrap(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_system_message(&self, text: TextComponent) {
|
pub fn send_system_message(&self, text: TextComponent) {
|
||||||
|
|||||||
@ -170,10 +170,7 @@ fn main() -> io::Result<()> {
|
|||||||
if closed {
|
if closed {
|
||||||
if let Some(player) = players.remove(&token) {
|
if let Some(player) = players.remove(&token) {
|
||||||
player.remove().await;
|
player.remove().await;
|
||||||
dbg!("b");
|
|
||||||
let connection = &mut player.client.connection.lock();
|
let connection = &mut player.client.connection.lock();
|
||||||
dbg!("c");
|
|
||||||
|
|
||||||
poll.registry().deregister(connection.by_ref())?;
|
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
|
/// Generates a new entity id
|
||||||
/// This should be global
|
/// This should be global
|
||||||
pub fn new_entity_id(&self) -> EntityId {
|
pub fn new_entity_id(&self) -> EntityId {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use pumpkin_entity::{entity_type::EntityType, EntityId};
|
|||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
client::play::{
|
client::play::{
|
||||||
CChunkData, CGameEvent, CLogin, CPlayerAbilities, CPlayerInfoUpdate, CRemoveEntities,
|
CChunkData, CGameEvent, CLogin, CPlayerAbilities, CPlayerInfoUpdate, CRemoveEntities,
|
||||||
CRemovePlayerInfo, CSetEntityMetadata, CSpawnEntity, Metadata, PlayerAction,
|
CRemovePlayerInfo, CSetEntityMetadata, CSpawnEntity, GameEvent, Metadata, PlayerAction,
|
||||||
},
|
},
|
||||||
uuid::UUID,
|
uuid::UUID,
|
||||||
ClientPacket, VarInt,
|
ClientPacket, VarInt,
|
||||||
@ -216,8 +216,10 @@ impl World {
|
|||||||
self.broadcast_packet_all(&packet)
|
self.broadcast_packet_all(&packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start waiting for level chunks
|
// Start waiting for level chunks, Sets the "Loading Terrain" screen
|
||||||
player.client.send_packet(&CGameEvent::new(13, 0.0));
|
player
|
||||||
|
.client
|
||||||
|
.send_packet(&CGameEvent::new(GameEvent::StartWaitingChunks, 0.0));
|
||||||
|
|
||||||
// Spawn in inital chunks
|
// Spawn in inital chunks
|
||||||
player_chunker::player_join(self, player.clone()).await;
|
player_chunker::player_join(self, player.clone()).await;
|
||||||
@ -258,13 +260,9 @@ impl World {
|
|||||||
dbg!("DONE CHUNKS", inst.elapsed());
|
dbg!("DONE CHUNKS", inst.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_by_entityid(&self, from: &Player, id: EntityId) -> Option<Arc<Player>> {
|
/// Gets a Player by entity id
|
||||||
for (_, player) in self
|
pub fn get_player_by_entityid(&self, id: EntityId) -> Option<Arc<Player>> {
|
||||||
.current_players
|
for (_, player) in self.current_players.lock().iter() {
|
||||||
.lock()
|
|
||||||
.iter()
|
|
||||||
.filter(|c| c.0 != &from.client.token)
|
|
||||||
{
|
|
||||||
if player.entity_id() == id {
|
if player.entity_id() == id {
|
||||||
return Some(player.clone());
|
return Some(player.clone());
|
||||||
}
|
}
|
||||||
@ -272,6 +270,16 @@ impl World {
|
|||||||
None
|
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>) {
|
pub fn add_player(&self, token: Token, player: Arc<Player>) {
|
||||||
self.current_players.lock().insert(token, player);
|
self.current_players.lock().insert(token, player);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user