Add Chat support
This commit is contained in:
parent
1076cc69f0
commit
fe8cd334e1
@ -57,7 +57,7 @@ Pumpkin is currently under heavy development.
|
|||||||
- [ ] Player Inventory
|
- [ ] Player Inventory
|
||||||
- [ ] Player Attack
|
- [ ] Player Attack
|
||||||
- Server
|
- Server
|
||||||
- [ ] Chat
|
- [x] Chat
|
||||||
- [x] Commands
|
- [x] Commands
|
||||||
|
|
||||||
Check out our [Github Project](https://github.com/users/Snowiiii/projects/12/views/1) to see current progress
|
Check out our [Github Project](https://github.com/users/Snowiiii/projects/12/views/1) to see current progress
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use serde::{ser, Serialize};
|
use serde::{
|
||||||
|
ser::{self},
|
||||||
|
Serialize,
|
||||||
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::VarInt;
|
|
||||||
|
|
||||||
use super::ByteBuffer;
|
use super::ByteBuffer;
|
||||||
|
|
||||||
pub struct Serializer {
|
pub struct Serializer {
|
||||||
@ -126,10 +127,9 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
|||||||
self.output.put_bool(false);
|
self.output.put_bool(false);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||||
if let Some(len) = len {
|
// here is where all arrays/list getting written, usally we prefix the length of every length with an var int. The problem is
|
||||||
self.output.put_var_int(&VarInt(len as i32));
|
// that byte arrays also getting thrown in here, and we don't want to prefix them
|
||||||
}
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||||
@ -137,7 +137,6 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
|||||||
T: ?Sized + Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
self.output.put_bool(true);
|
self.output.put_bool(true);
|
||||||
dbg!("aa");
|
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
||||||
@ -288,7 +287,7 @@ impl<'a> ser::SerializeTupleVariant for &'a mut Serializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn end(self) -> Result<(), Self::Error> {
|
fn end(self) -> Result<(), Self::Error> {
|
||||||
todo!()
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,42 +1,33 @@
|
|||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{bytebuf::ByteBuffer, ClientPacket, VarInt};
|
use crate::{RawBytes, VarInt};
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
#[packet(0x01)]
|
#[packet(0x01)]
|
||||||
pub struct CEncryptionRequest<'a> {
|
pub struct CEncryptionRequest<'a> {
|
||||||
server_id: &'a str, // 20
|
server_id: &'a str, // 20
|
||||||
public_key_length: VarInt,
|
public_key_length: VarInt,
|
||||||
public_key: &'a [u8],
|
public_key: RawBytes<'a>,
|
||||||
verify_token_length: VarInt,
|
verify_token_length: VarInt,
|
||||||
verify_token: &'a [u8],
|
verify_token: RawBytes<'a>,
|
||||||
should_authenticate: bool,
|
should_authenticate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CEncryptionRequest<'a> {
|
impl<'a> CEncryptionRequest<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
server_id: &'a str,
|
server_id: &'a str,
|
||||||
public_key: &'a [u8],
|
public_key: RawBytes<'a>,
|
||||||
verify_token: &'a [u8],
|
verify_token: RawBytes<'a>,
|
||||||
should_authenticate: bool,
|
should_authenticate: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
server_id,
|
server_id,
|
||||||
public_key_length: public_key.len().into(),
|
public_key_length: public_key.0.len().into(),
|
||||||
public_key,
|
public_key,
|
||||||
verify_token_length: verify_token.len().into(),
|
verify_token_length: verify_token.0.len().into(),
|
||||||
verify_token,
|
verify_token,
|
||||||
should_authenticate,
|
should_authenticate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ClientPacket for CEncryptionRequest<'a> {
|
|
||||||
fn write(&self, bytebuf: &mut ByteBuffer) {
|
|
||||||
bytebuf.put_string(self.server_id);
|
|
||||||
bytebuf.put_var_int(&self.public_key_length);
|
|
||||||
bytebuf.put_slice(self.public_key);
|
|
||||||
bytebuf.put_var_int(&self.verify_token_length);
|
|
||||||
bytebuf.put_slice(self.verify_token);
|
|
||||||
bytebuf.put_bool(self.should_authenticate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
37
pumpkin-protocol/src/client/play/c_disguised_chat_message.rs
Normal file
37
pumpkin-protocol/src/client/play/c_disguised_chat_message.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use pumpkin_macros::packet;
|
||||||
|
|
||||||
|
use crate::{text::TextComponent, ClientPacket, VarInt};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
#[packet(0x1E)]
|
||||||
|
pub struct CDisguisedChatMessage {
|
||||||
|
message: TextComponent,
|
||||||
|
chat_type: VarInt,
|
||||||
|
sender_name: TextComponent,
|
||||||
|
target_name: Option<TextComponent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CDisguisedChatMessage {
|
||||||
|
pub fn new(
|
||||||
|
message: TextComponent,
|
||||||
|
chat_type: VarInt,
|
||||||
|
sender_name: TextComponent,
|
||||||
|
target_name: Option<TextComponent>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
message,
|
||||||
|
chat_type,
|
||||||
|
sender_name,
|
||||||
|
target_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientPacket for CDisguisedChatMessage {
|
||||||
|
fn write(&self, bytebuf: &mut crate::bytebuf::ByteBuffer) {
|
||||||
|
bytebuf.put_slice(&self.message.encode());
|
||||||
|
bytebuf.put_var_int(&self.chat_type);
|
||||||
|
bytebuf.put_slice(&self.sender_name.encode());
|
||||||
|
bytebuf.put_option(&self.target_name, |p, v| p.put_slice(&v.encode()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ use crate::VarInt;
|
|||||||
pub struct CLogin {
|
pub struct CLogin {
|
||||||
entity_id: i32,
|
entity_id: i32,
|
||||||
is_hardcore: bool,
|
is_hardcore: bool,
|
||||||
|
dimension_count: VarInt,
|
||||||
dimension_names: Vec<String>,
|
dimension_names: Vec<String>,
|
||||||
max_players: VarInt,
|
max_players: VarInt,
|
||||||
view_distance: VarInt,
|
view_distance: VarInt,
|
||||||
@ -53,6 +54,7 @@ impl CLogin {
|
|||||||
Self {
|
Self {
|
||||||
entity_id,
|
entity_id,
|
||||||
is_hardcore,
|
is_hardcore,
|
||||||
|
dimension_count: VarInt(dimension_names.len() as i32),
|
||||||
dimension_names,
|
dimension_names,
|
||||||
max_players,
|
max_players,
|
||||||
view_distance,
|
view_distance,
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
use num_derive::FromPrimitive;
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
|
use pumpkin_macros::packet;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{text::TextComponent, VarInt};
|
use crate::{text::TextComponent, VarInt};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct PlayerChatMessage<'a> {
|
#[packet(0x39)]
|
||||||
|
pub struct CPlayerChatMessage<'a> {
|
||||||
sender: uuid::Uuid,
|
sender: uuid::Uuid,
|
||||||
index: VarInt,
|
index: VarInt,
|
||||||
message_signature: Option<&'a [u8]>,
|
message_signature: Option<&'a [u8]>,
|
||||||
@ -20,7 +22,7 @@ pub struct PlayerChatMessage<'a> {
|
|||||||
target_name: Option<TextComponent>,
|
target_name: Option<TextComponent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PlayerChatMessage<'a> {
|
impl<'a> CPlayerChatMessage<'a> {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sender: uuid::Uuid,
|
sender: uuid::Uuid,
|
||||||
@ -59,7 +61,7 @@ pub struct PreviousMessage<'a> {
|
|||||||
signature: Option<&'a [u8]>,
|
signature: Option<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromPrimitive)]
|
#[derive(FromPrimitive, ToPrimitive)]
|
||||||
pub enum FilterType {
|
pub enum FilterType {
|
||||||
/// Message is not filtered at all
|
/// Message is not filtered at all
|
||||||
PassThrough,
|
PassThrough,
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use serde::Serialize;
|
|||||||
|
|
||||||
use crate::text::TextComponent;
|
use crate::text::TextComponent;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Clone)]
|
||||||
#[packet(0x6C)]
|
#[packet(0x6C)]
|
||||||
pub struct CSystemChatMessge {
|
pub struct CSystemChatMessge {
|
||||||
content: TextComponent,
|
content: TextComponent,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
mod c_change_difficulty;
|
mod c_change_difficulty;
|
||||||
mod c_chunk_data_update_light;
|
mod c_chunk_data_update_light;
|
||||||
|
mod c_disguised_chat_message;
|
||||||
mod c_entity_animation;
|
mod c_entity_animation;
|
||||||
mod c_entity_metadata;
|
mod c_entity_metadata;
|
||||||
mod c_game_event;
|
mod c_game_event;
|
||||||
@ -21,6 +22,7 @@ mod player_action;
|
|||||||
|
|
||||||
pub use c_change_difficulty::*;
|
pub use c_change_difficulty::*;
|
||||||
pub use c_chunk_data_update_light::*;
|
pub use c_chunk_data_update_light::*;
|
||||||
|
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_game_event::*;
|
pub use c_game_event::*;
|
||||||
|
|||||||
@ -91,6 +91,16 @@ impl VarInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RawBytes<'a>(pub &'a [u8]);
|
||||||
|
impl<'a> Serialize for RawBytes<'a> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_bytes(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<i32> for VarInt {
|
impl From<i32> for VarInt {
|
||||||
fn from(value: i32) -> Self {
|
fn from(value: i32) -> Self {
|
||||||
VarInt(value)
|
VarInt(value)
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
mod s_chat_command;
|
mod s_chat_command;
|
||||||
|
mod s_chat_message;
|
||||||
mod s_confirm_teleport;
|
mod s_confirm_teleport;
|
||||||
mod s_player_command;
|
mod s_player_command;
|
||||||
mod s_player_position;
|
mod s_player_position;
|
||||||
@ -7,6 +8,7 @@ mod s_player_rotation;
|
|||||||
mod s_swing_arm;
|
mod s_swing_arm;
|
||||||
|
|
||||||
pub use s_chat_command::*;
|
pub use s_chat_command::*;
|
||||||
|
pub use s_chat_message::*;
|
||||||
pub use s_confirm_teleport::*;
|
pub use s_confirm_teleport::*;
|
||||||
pub use s_player_command::*;
|
pub use s_player_command::*;
|
||||||
pub use s_player_position::*;
|
pub use s_player_position::*;
|
||||||
|
|||||||
29
pumpkin-protocol/src/server/play/s_chat_message.rs
Normal file
29
pumpkin-protocol/src/server/play/s_chat_message.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use pumpkin_macros::packet;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
bytebuf::{ByteBuffer, DeserializerError},
|
||||||
|
ServerPacket,
|
||||||
|
};
|
||||||
|
|
||||||
|
// derive(Deserialize)]
|
||||||
|
#[packet(0x06)]
|
||||||
|
pub struct SChatMessage {
|
||||||
|
pub message: String,
|
||||||
|
pub timestamp: i64,
|
||||||
|
pub salt: i64,
|
||||||
|
pub signature: Option<Vec<u8>>,
|
||||||
|
// pub messagee_count: VarInt,
|
||||||
|
// acknowledged: BitSet,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerPacket for SChatMessage {
|
||||||
|
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
|
||||||
|
Ok(Self {
|
||||||
|
message: bytebuf.get_string().unwrap(),
|
||||||
|
timestamp: bytebuf.get_i64(),
|
||||||
|
salt: bytebuf.get_i64(),
|
||||||
|
signature: bytebuf.get_option(|v| v.get_slice().to_vec()),
|
||||||
|
//messagee_count: bytebuf.get_var_int(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,7 +15,7 @@ impl serde::Serialize for TextComponent {
|
|||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
serializer.serialize_bytes(&self.encode())
|
serializer.serialize_bytes(self.encode().as_slice())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -84,7 +84,6 @@ pub fn unpack_textures(property: Property, config: &TextureConfig) {
|
|||||||
// TODO: no unwrap
|
// TODO: no unwrap
|
||||||
let from64 = general_purpose::STANDARD.decode(property.value).unwrap();
|
let from64 = general_purpose::STANDARD.decode(property.value).unwrap();
|
||||||
let textures: ProfileTextures = serde_json::from_slice(&from64).unwrap();
|
let textures: ProfileTextures = serde_json::from_slice(&from64).unwrap();
|
||||||
dbg!(&textures);
|
|
||||||
for texture in textures.textures {
|
for texture in textures.textures {
|
||||||
is_texture_url_valid(Url::parse(&texture.1.url).unwrap(), config);
|
is_texture_url_valid(Url::parse(&texture.1.url).unwrap(), config);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use pumpkin_protocol::{
|
|||||||
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
|
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
|
||||||
status::{SPingRequest, SStatusRequest},
|
status::{SPingRequest, SStatusRequest},
|
||||||
},
|
},
|
||||||
ConnectionState, KnownPack,
|
ConnectionState, KnownPack, RawBytes,
|
||||||
};
|
};
|
||||||
use pumpkin_registry::Registry;
|
use pumpkin_registry::Registry;
|
||||||
use rsa::Pkcs1v15Encrypt;
|
use rsa::Pkcs1v15Encrypt;
|
||||||
@ -64,8 +64,8 @@ impl Client {
|
|||||||
let public_key_der = &server.public_key_der;
|
let public_key_der = &server.public_key_der;
|
||||||
let packet = CEncryptionRequest::new(
|
let packet = CEncryptionRequest::new(
|
||||||
"",
|
"",
|
||||||
public_key_der,
|
RawBytes(public_key_der),
|
||||||
&verify_token,
|
RawBytes(&verify_token),
|
||||||
server.base_config.online_mode, // TODO
|
server.base_config.online_mode, // TODO
|
||||||
);
|
);
|
||||||
self.send_packet(packet);
|
self.send_packet(packet);
|
||||||
|
|||||||
@ -27,7 +27,7 @@ use pumpkin_protocol::{
|
|||||||
handshake::SHandShake,
|
handshake::SHandShake,
|
||||||
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
|
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
|
||||||
play::{
|
play::{
|
||||||
SChatCommand, SConfirmTeleport, SPlayerCommand, SPlayerPosition,
|
SChatCommand, SChatMessage, SConfirmTeleport, SPlayerCommand, SPlayerPosition,
|
||||||
SPlayerPositionRotation, SPlayerRotation, SSwingArm,
|
SPlayerPositionRotation, SPlayerRotation, SSwingArm,
|
||||||
},
|
},
|
||||||
status::{SPingRequest, SStatusRequest},
|
status::{SPingRequest, SStatusRequest},
|
||||||
@ -195,10 +195,13 @@ impl Client {
|
|||||||
SLoginStart::PACKET_ID => {
|
SLoginStart::PACKET_ID => {
|
||||||
self.handle_login_start(server, SLoginStart::read(bytebuf).unwrap())
|
self.handle_login_start(server, SLoginStart::read(bytebuf).unwrap())
|
||||||
}
|
}
|
||||||
SEncryptionResponse::PACKET_ID => self.handle_encryption_response(
|
SEncryptionResponse::PACKET_ID => {
|
||||||
server,
|
self.handle_encryption_response(
|
||||||
SEncryptionResponse::read(bytebuf).unwrap(),
|
server,
|
||||||
).await,
|
SEncryptionResponse::read(bytebuf).unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
SLoginPluginResponse::PACKET_ID => self
|
SLoginPluginResponse::PACKET_ID => self
|
||||||
.handle_plugin_response(server, SLoginPluginResponse::read(bytebuf).unwrap()),
|
.handle_plugin_response(server, SLoginPluginResponse::read(bytebuf).unwrap()),
|
||||||
SLoginAcknowledged::PACKET_ID => self
|
SLoginAcknowledged::PACKET_ID => self
|
||||||
@ -261,6 +264,9 @@ impl Client {
|
|||||||
SSwingArm::PACKET_ID => {
|
SSwingArm::PACKET_ID => {
|
||||||
self.handle_swing_arm(server, SSwingArm::read(bytebuf).unwrap())
|
self.handle_swing_arm(server, SSwingArm::read(bytebuf).unwrap())
|
||||||
}
|
}
|
||||||
|
SChatMessage::PACKET_ID => {
|
||||||
|
self.handle_chat_message(server, SChatMessage::read(bytebuf).unwrap())
|
||||||
|
}
|
||||||
_ => log::error!("Failed to handle player packet id {}", packet.id.0),
|
_ => log::error!("Failed to handle player packet id {}", packet.id.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
client::play::{
|
client::play::{
|
||||||
Animation, CEntityAnimation, CHeadRot, CUpdateEntityPos, CUpdateEntityPosRot,
|
Animation, CEntityAnimation, CHeadRot, CSystemChatMessge, CUpdateEntityPos,
|
||||||
CUpdateEntityRot,
|
CUpdateEntityPosRot, CUpdateEntityRot,
|
||||||
},
|
},
|
||||||
server::play::{
|
server::play::{
|
||||||
SChatCommand, SConfirmTeleport, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation,
|
SChatCommand, SChatMessage, SConfirmTeleport, SPlayerCommand, SPlayerPosition,
|
||||||
SPlayerRotation, SSwingArm,
|
SPlayerPositionRotation, SPlayerRotation, SSwingArm,
|
||||||
},
|
},
|
||||||
|
text::TextComponent,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -171,4 +172,45 @@ impl Client {
|
|||||||
let id = player.entity_id();
|
let id = player.entity_id();
|
||||||
server.broadcast_packet_expect(self, CEntityAnimation::new(id.into(), animation as u8))
|
server.broadcast_packet_expect(self, CEntityAnimation::new(id.into(), animation as u8))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_chat_message(&mut self, server: &mut Server, chat_message: SChatMessage) {
|
||||||
|
let message = chat_message.message;
|
||||||
|
// TODO: filter message & validation
|
||||||
|
let gameprofile = self.gameprofile.as_ref().unwrap();
|
||||||
|
dbg!("got message");
|
||||||
|
// yeah a "raw system message", the ugly way to do that, but it works
|
||||||
|
server.broadcast_packet(
|
||||||
|
self,
|
||||||
|
CSystemChatMessge::new(
|
||||||
|
TextComponent::from(format!("{}: {}", gameprofile.name, message)),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
/*server.broadcast_packet(
|
||||||
|
self,
|
||||||
|
CPlayerChatMessage::new(
|
||||||
|
gameprofile.id,
|
||||||
|
0.into(),
|
||||||
|
None,
|
||||||
|
message.clone(),
|
||||||
|
chat_message.timestamp,
|
||||||
|
chat_message.salt,
|
||||||
|
&[],
|
||||||
|
Some(TextComponent::from(message.clone())),
|
||||||
|
pumpkin_protocol::VarInt(FilterType::PassThrough as i32),
|
||||||
|
0.into(),
|
||||||
|
TextComponent::from(gameprofile.name.clone()),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
) */
|
||||||
|
/* server.broadcast_packet(
|
||||||
|
self,
|
||||||
|
CDisguisedChatMessage::new(
|
||||||
|
TextComponent::from(message.clone()),
|
||||||
|
VarInt(0),
|
||||||
|
gameprofile.name.clone().into(),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
) */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ pub trait Command<'a> {
|
|||||||
fn on_execute(sender: &mut CommandSender<'a>, command: String);
|
fn on_execute(sender: &mut CommandSender<'a>, command: String);
|
||||||
|
|
||||||
/// Specifies wether the Command Sender has to be a Player
|
/// Specifies wether the Command Sender has to be a Player
|
||||||
|
/// TODO: implement
|
||||||
fn player_required() -> bool {
|
fn player_required() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -155,6 +155,7 @@ impl Server {
|
|||||||
0.into(),
|
0.into(),
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
|
dbg!("sending abilities");
|
||||||
// player abilities
|
// player abilities
|
||||||
client.send_packet(CPlayerAbilities::new(0x02, 00.2, 0.1));
|
client.send_packet(CPlayerAbilities::new(0x02, 00.2, 0.1));
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user