216 lines
6.2 KiB
Rust
216 lines
6.2 KiB
Rust
use crate::{
|
|
codec::var_uint::VarUInt,
|
|
serial::{PacketRead, PacketWrite},
|
|
};
|
|
use pumpkin_macros::packet;
|
|
use std::io::{Error, ErrorKind, Read, Write};
|
|
|
|
#[derive(Debug)]
|
|
#[packet(9)]
|
|
pub struct SText {
|
|
pub needs_translation: bool,
|
|
pub r#type: TextPacketType,
|
|
pub source_name: String,
|
|
pub message: String,
|
|
pub parameters: Vec<String>,
|
|
pub xuid: String,
|
|
pub platform_chat_id: String,
|
|
pub filtered_message: Option<String>,
|
|
}
|
|
|
|
impl SText {
|
|
#[must_use]
|
|
pub fn new(message: String, source_name: String) -> Self {
|
|
Self {
|
|
needs_translation: false,
|
|
r#type: TextPacketType::Chat,
|
|
source_name,
|
|
message: if message.is_empty() {
|
|
" ".to_string()
|
|
} else {
|
|
message
|
|
},
|
|
parameters: Vec::new(),
|
|
xuid: String::new(),
|
|
platform_chat_id: String::new(),
|
|
filtered_message: None,
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn system_message(message: String) -> Self {
|
|
Self {
|
|
needs_translation: false,
|
|
r#type: TextPacketType::System,
|
|
source_name: String::new(),
|
|
message: if message.is_empty() {
|
|
" ".to_string()
|
|
} else {
|
|
message
|
|
},
|
|
parameters: Vec::new(),
|
|
xuid: String::new(),
|
|
platform_chat_id: String::new(),
|
|
filtered_message: None,
|
|
}
|
|
}
|
|
|
|
const fn get_category(&self) -> u8 {
|
|
match self.r#type {
|
|
TextPacketType::Raw
|
|
| TextPacketType::Tip
|
|
| TextPacketType::System
|
|
| TextPacketType::JsonWhisper
|
|
| TextPacketType::JsonAnnouncement
|
|
| TextPacketType::Json => 0, // CATEGORY_MESSAGE_ONLY
|
|
|
|
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => 1, // CATEGORY_AUTHORED_MESSAGE
|
|
|
|
TextPacketType::Translation | TextPacketType::Popup | TextPacketType::JukeboxPopup => 2, // CATEGORY_MESSAGE_WITH_PARAMETERS
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PacketRead for SText {
|
|
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
|
let needs_translation = bool::read(reader)?;
|
|
|
|
let _category = u8::read(reader)?;
|
|
|
|
let r#type = TextPacketType::read(reader)?;
|
|
|
|
let mut source_name = String::new();
|
|
#[expect(unused)]
|
|
let mut message = String::new();
|
|
let mut parameters = Vec::new();
|
|
|
|
match r#type {
|
|
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => {
|
|
source_name = String::read(reader)?;
|
|
message = String::read(reader)?;
|
|
}
|
|
TextPacketType::Raw
|
|
| TextPacketType::Tip
|
|
| TextPacketType::System
|
|
| TextPacketType::JsonWhisper
|
|
| TextPacketType::Json
|
|
| TextPacketType::JsonAnnouncement => {
|
|
message = String::read(reader)?;
|
|
}
|
|
TextPacketType::Translation | TextPacketType::Popup | TextPacketType::JukeboxPopup => {
|
|
message = String::read(reader)?;
|
|
let count = VarUInt::read(reader)?.0 as usize;
|
|
for _ in 0..count {
|
|
parameters.push(String::read(reader)?);
|
|
}
|
|
}
|
|
}
|
|
|
|
let xuid = String::read(reader)?;
|
|
let platform_chat_id = String::read(reader)?;
|
|
|
|
let filtered_message = bool::read(reader)?
|
|
.then(|| String::read(reader))
|
|
.transpose()?;
|
|
|
|
Ok(Self {
|
|
needs_translation,
|
|
r#type,
|
|
source_name,
|
|
message,
|
|
parameters,
|
|
xuid,
|
|
platform_chat_id,
|
|
filtered_message,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl PacketWrite for SText {
|
|
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
|
self.needs_translation.write(writer)?;
|
|
|
|
let category = self.get_category();
|
|
category.write(writer)?;
|
|
|
|
self.r#type.write(writer)?;
|
|
|
|
match self.r#type {
|
|
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => {
|
|
self.source_name.write(writer)?;
|
|
self.message.write(writer)?;
|
|
}
|
|
TextPacketType::Raw
|
|
| TextPacketType::Tip
|
|
| TextPacketType::System
|
|
| TextPacketType::JsonWhisper
|
|
| TextPacketType::Json
|
|
| TextPacketType::JsonAnnouncement => {
|
|
self.message.write(writer)?;
|
|
}
|
|
TextPacketType::Translation | TextPacketType::Popup | TextPacketType::JukeboxPopup => {
|
|
self.message.write(writer)?;
|
|
VarUInt(self.parameters.len() as u32).write(writer)?;
|
|
for param in &self.parameters {
|
|
param.write(writer)?;
|
|
}
|
|
}
|
|
}
|
|
|
|
self.xuid.write(writer)?;
|
|
self.platform_chat_id.write(writer)?;
|
|
|
|
if let Some(msg) = &self.filtered_message {
|
|
true.write(writer)?;
|
|
msg.write(writer)?;
|
|
} else {
|
|
false.write(writer)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
#[repr(u8)]
|
|
pub enum TextPacketType {
|
|
Raw = 0,
|
|
Chat = 1,
|
|
Translation = 2,
|
|
Popup = 3,
|
|
JukeboxPopup = 4,
|
|
Tip = 5,
|
|
System = 6,
|
|
Whisper = 7,
|
|
Announcement = 8,
|
|
JsonWhisper = 9,
|
|
Json = 10,
|
|
JsonAnnouncement = 11,
|
|
}
|
|
|
|
impl PacketWrite for TextPacketType {
|
|
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
|
(*self as u8).write(writer)
|
|
}
|
|
}
|
|
|
|
impl PacketRead for TextPacketType {
|
|
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
|
match u8::read(reader)? {
|
|
0 => Ok(Self::Raw),
|
|
1 => Ok(Self::Chat),
|
|
2 => Ok(Self::Translation),
|
|
3 => Ok(Self::Popup),
|
|
4 => Ok(Self::JukeboxPopup),
|
|
5 => Ok(Self::Tip),
|
|
6 => Ok(Self::System),
|
|
7 => Ok(Self::Whisper),
|
|
8 => Ok(Self::Announcement),
|
|
9 => Ok(Self::JsonWhisper),
|
|
10 => Ok(Self::Json),
|
|
11 => Ok(Self::JsonAnnouncement),
|
|
_ => Err(Error::new(ErrorKind::InvalidData, "Unknown Text Type")),
|
|
}
|
|
}
|
|
}
|