chore(net): change get_string to get_str
changed return value from `String` to `Box<str>` which is smaller and makes more sense since we don't mutate packet data String — 24 bytes (ptr + len + capacity) Box<str> — 16 bytes (ptr + len)
This commit is contained in:
parent
8e7195c39e
commit
3303bb7b97
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2149,6 +2149,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
@ -3848,6 +3857,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex-automata",
|
||||
"sharded-slab",
|
||||
|
||||
@ -171,6 +171,7 @@ tracing = { version = "0.1.44", default-features = false, features = ["std", "at
|
||||
tracing-subscriber = { version = "0.3.23", default-features = false, features = [
|
||||
"env-filter",
|
||||
"fmt",
|
||||
"ansi",
|
||||
"time",
|
||||
"std",
|
||||
] }
|
||||
|
||||
@ -87,7 +87,7 @@ impl UDPNetworkDecoder {
|
||||
|
||||
pub async fn get_packet_payload(
|
||||
&mut self,
|
||||
full_packet: Vec<u8>,
|
||||
mut full_packet: Vec<u8>,
|
||||
) -> Result<Vec<u8>, PacketDecodeError> {
|
||||
if full_packet.is_empty() {
|
||||
return Err(PacketDecodeError::MalformedLength("Empty packet".into()));
|
||||
@ -104,7 +104,7 @@ impl UDPNetworkDecoder {
|
||||
|
||||
// If compression is NOT enabled yet, the payload starts at index 1.
|
||||
if self.compression.is_none() {
|
||||
return Ok(full_packet[1..].to_vec());
|
||||
return Ok(full_packet.split_off(1));
|
||||
}
|
||||
|
||||
// If compression IS enabled, Bedrock expects a compression method byte at index 1.
|
||||
@ -125,7 +125,7 @@ impl UDPNetworkDecoder {
|
||||
}
|
||||
0xff => {
|
||||
// None (Compression enabled but this specific packet is raw)
|
||||
Ok(full_packet[data_start..].to_vec())
|
||||
Ok(full_packet.split_off(2))
|
||||
}
|
||||
_ => Err(PacketDecodeError::FailedDecompression(format!(
|
||||
"Unsupported compression method: 0x{compression_method:02x}"
|
||||
|
||||
@ -27,7 +27,7 @@ pub struct CPlayerChatMessage {
|
||||
/// The RSA signature (256 bytes) verifying the message's authenticity.
|
||||
pub message_signature: Option<Box<[u8]>>,
|
||||
/// The raw plain-text content of the message.
|
||||
pub message: String,
|
||||
pub message: Box<str>,
|
||||
/// Epoch timestamp (milliseconds) when the message was sent.
|
||||
pub timestamp: i64,
|
||||
/// A random 64-bit value used to ensure signature uniqueness.
|
||||
@ -58,7 +58,7 @@ impl CPlayerChatMessage {
|
||||
sender: uuid::Uuid,
|
||||
index: VarInt,
|
||||
message_signature: Option<Box<[u8]>>,
|
||||
message: String,
|
||||
message: Box<str>,
|
||||
timestamp: i64,
|
||||
salt: i64,
|
||||
previous_messages: Box<[PreviousMessage]>,
|
||||
|
||||
@ -2,7 +2,7 @@ use std::io::Read;
|
||||
|
||||
use pumpkin_data::packet::serverbound::CONFIG_COOKIE_RESPONSE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
use crate::{ReadingError, ServerPacket, ser::NetworkReadExt};
|
||||
|
||||
@ -16,7 +16,7 @@ const MAX_COOKIE_LENGTH: usize = 5120;
|
||||
#[java_packet(CONFIG_COOKIE_RESPONSE)]
|
||||
pub struct SConfigCookieResponse {
|
||||
/// The unique identifier for the cookie being returned
|
||||
pub key: ResourceLocation,
|
||||
pub key: Box<str>,
|
||||
/// Indicates whether a payload is attached to this response
|
||||
pub has_payload: bool,
|
||||
/// The actual data stored in the cookie. Limited to 5120 bytes
|
||||
@ -26,7 +26,7 @@ pub struct SConfigCookieResponse {
|
||||
impl ServerPacket for SConfigCookieResponse {
|
||||
fn read(read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||
let mut read = read;
|
||||
let key = read.get_string()?;
|
||||
let key = read.get_str()?;
|
||||
let has_payload = read.get_bool()?;
|
||||
|
||||
if !has_payload {
|
||||
|
||||
@ -2,7 +2,7 @@ use std::io::Read;
|
||||
|
||||
use pumpkin_data::packet::serverbound::CONFIG_CUSTOM_PAYLOAD;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
use crate::{ReadingError, ServerPacket, ser::NetworkReadExt};
|
||||
|
||||
@ -17,7 +17,7 @@ const MAX_PAYLOAD_SIZE: usize = 1_048_576;
|
||||
pub struct SPluginMessage {
|
||||
/// The name of the channel used to distinguish different types of messages.
|
||||
/// Example: `minecraft:brand` or `velocity:main`.
|
||||
pub channel: ResourceLocation,
|
||||
pub channel: Box<str>,
|
||||
/// The payload sent by the client.
|
||||
pub data: Box<[u8]>,
|
||||
}
|
||||
@ -25,7 +25,7 @@ pub struct SPluginMessage {
|
||||
impl ServerPacket for SPluginMessage {
|
||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||
Ok(Self {
|
||||
channel: read.get_string()?,
|
||||
channel: read.get_str()?,
|
||||
data: read.read_remaining_to_boxed_slice(MAX_PAYLOAD_SIZE)?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ pub struct SHandShake {
|
||||
/// The protocol version of the client (e.g., 767 for 1.21).
|
||||
pub protocol_version: VarInt,
|
||||
/// The hostname or IP used by the client to connect
|
||||
pub server_address: String,
|
||||
pub server_address: Box<str>,
|
||||
/// The port number used by the client to connect
|
||||
pub server_port: u16,
|
||||
/// The state the client wants to transition to (1 for Status, 2 for Login)
|
||||
@ -28,7 +28,7 @@ impl ServerPacket for SHandShake {
|
||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||
Ok(Self {
|
||||
protocol_version: read.get_var_int()?,
|
||||
server_address: read.get_string_bounded(255)?,
|
||||
server_address: read.get_str_bounded(255)?,
|
||||
server_port: read.get_u16_be()?,
|
||||
next_state: read
|
||||
.get_var_int()?
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use pumpkin_data::packet::serverbound::LOGIN_COOKIE_RESPONSE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
use std::io::Read;
|
||||
|
||||
use crate::{
|
||||
@ -12,7 +12,7 @@ use crate::{
|
||||
/// Response to a `CCookieRequest` (login) from the server.
|
||||
/// The Notchian server only accepts responses of up to 5 kiB in size.
|
||||
pub struct SLoginCookieResponse {
|
||||
pub key: ResourceLocation,
|
||||
pub key: Box<str>,
|
||||
pub payload: Option<Box<[u8]>>, // 5120,
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ const MAX_COOKIE_LENGTH: usize = 5120;
|
||||
|
||||
impl ServerPacket for SLoginCookieResponse {
|
||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||
let key = read.get_string()?;
|
||||
let key = read.get_str()?;
|
||||
let has_payload = read.get_bool()?;
|
||||
|
||||
if !has_payload {
|
||||
|
||||
@ -13,14 +13,14 @@ use crate::{
|
||||
#[java_packet(LOGIN_HELLO)]
|
||||
#[derive(Serialize)]
|
||||
pub struct SLoginStart {
|
||||
pub name: String, // 16
|
||||
pub name: Box<str>, // 16
|
||||
pub uuid: uuid::Uuid,
|
||||
}
|
||||
|
||||
impl ServerPacket for SLoginStart {
|
||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||
Ok(Self {
|
||||
name: read.get_string_bounded(16)?,
|
||||
name: read.get_str_bounded(16)?,
|
||||
uuid: read.get_uuid()?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ use crate::{
|
||||
|
||||
#[java_packet(PLAY_CHAT)]
|
||||
pub struct SChatMessage {
|
||||
pub message: String,
|
||||
pub message: Box<str>,
|
||||
pub timestamp: i64,
|
||||
pub salt: i64,
|
||||
pub signature: Option<Box<[u8]>>,
|
||||
@ -25,7 +25,7 @@ pub struct SChatMessage {
|
||||
impl ServerPacket for SChatMessage {
|
||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||
Ok(Self {
|
||||
message: read.get_string_bounded(256)?,
|
||||
message: read.get_str_bounded(256)?,
|
||||
timestamp: read.get_i64_be()?,
|
||||
salt: read.get_i64_be()?,
|
||||
signature: read.get_option(|v| v.read_boxed_slice(256))?,
|
||||
|
||||
@ -2,7 +2,7 @@ use std::io::Read;
|
||||
|
||||
use pumpkin_data::packet::serverbound::PLAY_COOKIE_RESPONSE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
use crate::{
|
||||
ServerPacket,
|
||||
@ -13,7 +13,7 @@ use crate::{
|
||||
/// Response to a `CCookieRequest` (play) from the server.
|
||||
/// The Notchian (vanilla) server only accepts responses of up to 5 KiB in size.
|
||||
pub struct SCookieResponse {
|
||||
pub key: ResourceLocation,
|
||||
pub key: Box<str>,
|
||||
pub payload: Option<Box<[u8]>>, // 5120,
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ const MAX_COOKIE_LENGTH: usize = 5120;
|
||||
|
||||
impl ServerPacket for SCookieResponse {
|
||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||
let key = read.get_string()?;
|
||||
let key = read.get_str()?;
|
||||
let has_payload = read.get_bool()?;
|
||||
|
||||
if !has_payload {
|
||||
|
||||
@ -2,7 +2,7 @@ use std::io::Read;
|
||||
|
||||
use pumpkin_data::packet::serverbound::PLAY_CUSTOM_PAYLOAD;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
use crate::{ReadingError, ServerPacket, ser::NetworkReadExt};
|
||||
|
||||
@ -17,7 +17,7 @@ const MAX_PAYLOAD_SIZE: usize = 32_767;
|
||||
pub struct SCustomPayload {
|
||||
/// The name of the channel used to distinguish different types of messages.
|
||||
/// Example: `minecraft:brand` or `voicechat:request_secret`.
|
||||
pub channel: ResourceLocation,
|
||||
pub channel: Box<str>,
|
||||
/// The payload sent by the client.
|
||||
pub data: Box<[u8]>,
|
||||
}
|
||||
@ -25,7 +25,7 @@ pub struct SCustomPayload {
|
||||
impl ServerPacket for SCustomPayload {
|
||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||
Ok(Self {
|
||||
channel: read.get_string()?,
|
||||
channel: read.get_str()?,
|
||||
data: read.read_remaining_to_boxed_slice(MAX_PAYLOAD_SIZE)?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -13,10 +13,10 @@ use crate::{
|
||||
pub struct SUpdateSign {
|
||||
pub location: BlockPos,
|
||||
pub is_front_text: bool,
|
||||
pub line_1: String,
|
||||
pub line_2: String,
|
||||
pub line_3: String,
|
||||
pub line_4: String,
|
||||
pub line_1: Box<str>,
|
||||
pub line_2: Box<str>,
|
||||
pub line_3: Box<str>,
|
||||
pub line_4: Box<str>,
|
||||
}
|
||||
|
||||
const MAX_LINE_LENGTH: usize = 386;
|
||||
@ -26,10 +26,10 @@ impl ServerPacket for SUpdateSign {
|
||||
Ok(Self {
|
||||
location: BlockPos::from_i64(read.get_i64_be()?),
|
||||
is_front_text: read.get_bool()?,
|
||||
line_1: read.get_string_bounded(MAX_LINE_LENGTH)?,
|
||||
line_2: read.get_string_bounded(MAX_LINE_LENGTH)?,
|
||||
line_3: read.get_string_bounded(MAX_LINE_LENGTH)?,
|
||||
line_4: read.get_string_bounded(MAX_LINE_LENGTH)?,
|
||||
line_1: read.get_str_bounded(MAX_LINE_LENGTH)?,
|
||||
line_2: read.get_str_bounded(MAX_LINE_LENGTH)?,
|
||||
line_3: read.get_str_bounded(MAX_LINE_LENGTH)?,
|
||||
line_4: read.get_str_bounded(MAX_LINE_LENGTH)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,11 +418,11 @@ pub struct Sample {
|
||||
// basically game profile
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct Property {
|
||||
pub name: String,
|
||||
pub name: Box<str>,
|
||||
// base 64
|
||||
pub value: String,
|
||||
pub value: Box<str>,
|
||||
// base 64
|
||||
pub signature: Option<String>,
|
||||
pub signature: Option<Box<str>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
||||
@ -101,7 +101,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
|
||||
}
|
||||
|
||||
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
|
||||
visitor.visit_str(&self.inner.get_string()?)
|
||||
visitor.visit_str(&self.inner.get_str()?)
|
||||
}
|
||||
|
||||
fn deserialize_bytes<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Self::Error> {
|
||||
|
||||
@ -60,8 +60,8 @@ pub trait NetworkReadExt {
|
||||
fn get_var_uint(&mut self) -> Result<VarUInt, ReadingError>;
|
||||
fn get_var_long(&mut self) -> Result<VarLong, ReadingError>;
|
||||
fn get_var_ulong(&mut self) -> Result<VarULong, ReadingError>;
|
||||
fn get_string_bounded(&mut self, bound: usize) -> Result<String, ReadingError>;
|
||||
fn get_string(&mut self) -> Result<String, ReadingError>;
|
||||
fn get_str_bounded(&mut self, bound: usize) -> Result<Box<str>, ReadingError>;
|
||||
fn get_str(&mut self) -> Result<Box<str>, ReadingError>;
|
||||
fn get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError>;
|
||||
fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError>;
|
||||
|
||||
@ -154,7 +154,7 @@ impl<R: Read> NetworkReadExt for R {
|
||||
VarULong::decode(self)
|
||||
}
|
||||
|
||||
fn get_string_bounded(&mut self, bound: usize) -> Result<String, ReadingError> {
|
||||
fn get_str_bounded(&mut self, bound: usize) -> Result<Box<str>, ReadingError> {
|
||||
let bytes_len = self.get_var_uint()?.0 as usize;
|
||||
|
||||
// We treat `bound` as the maximum number of Java `char`s allowed.
|
||||
@ -170,7 +170,7 @@ impl<R: Read> NetworkReadExt for R {
|
||||
|
||||
let data = self.read_boxed_slice(bytes_len)?;
|
||||
let string =
|
||||
String::from_utf8(data.into()).map_err(|e| ReadingError::Message(e.to_string()))?;
|
||||
std::str::from_utf8(&data).map_err(|e| ReadingError::Message(e.to_string()))?;
|
||||
|
||||
// Next, if we're able to find the (bound + 1)th UTF-16 character, the string is too big.
|
||||
if string.encode_utf16().nth(bound).is_some() {
|
||||
@ -179,11 +179,11 @@ impl<R: Read> NetworkReadExt for R {
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(string)
|
||||
Ok(string.into())
|
||||
}
|
||||
|
||||
fn get_string(&mut self) -> Result<String, ReadingError> {
|
||||
self.get_string_bounded(i32::MAX as usize)
|
||||
fn get_str(&mut self) -> Result<Box<str>, ReadingError> {
|
||||
self.get_str_bounded(i32::MAX as usize)
|
||||
}
|
||||
|
||||
fn get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError> {
|
||||
|
||||
@ -15,6 +15,7 @@ use std::{
|
||||
use crate::text::{TextComponentBase, TextContent, style::Style};
|
||||
|
||||
static VANILLA_EN_US_JSON: &str = include_str!("../../assets/en_us_java.json");
|
||||
static PUMPKIN_EN_US_JSON: &str = include_str!("../../assets/translations/en_us.json");
|
||||
static PUMPKIN_BRB_JSON: &str = include_str!("../../assets/translations/brb.json");
|
||||
static PUMPKIN_DE_DE_JSON: &str = include_str!("../../assets/translations/de_de.json");
|
||||
static PUMPKIN_ES_ES_JSON: &str = include_str!("../../assets/translations/es_es.json");
|
||||
@ -272,6 +273,8 @@ pub static TRANSLATIONS: LazyLock<Mutex<[HashMap<String, String>; Locale::COUNT]
|
||||
std::array::from_fn(|_| HashMap::new());
|
||||
let vanilla_en_us: HashMap<String, String> =
|
||||
serde_json::from_str(VANILLA_EN_US_JSON).expect("Could not parse en_us_java.json.");
|
||||
let pumpkin_en_us: HashMap<String, String> =
|
||||
serde_json::from_str(PUMPKIN_EN_US_JSON).expect("Could not parse en_us.json.");
|
||||
let pumpkin_brb: HashMap<String, String> =
|
||||
serde_json::from_str(PUMPKIN_BRB_JSON).expect("Could not parse brb.json.");
|
||||
let pumpkin_de_de: HashMap<String, String> =
|
||||
@ -322,6 +325,9 @@ pub static TRANSLATIONS: LazyLock<Mutex<[HashMap<String, String>; Locale::COUNT]
|
||||
for (key, value) in vanilla_en_us {
|
||||
array[Locale::EnUs as usize].insert(format!("minecraft:{key}"), value);
|
||||
}
|
||||
for (key, value) in pumpkin_en_us {
|
||||
array[Locale::EnUs as usize].insert(format!("pumpkin:{key}"), value);
|
||||
}
|
||||
for (key, value) in pumpkin_brb {
|
||||
array[Locale::Brb as usize].insert(format!("pumpkin:{key}"), value);
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::generation::proto_chunk::GenerationCache;
|
||||
use alter_ground::AlterGroundTreeDecorator;
|
||||
use attached_to_leaves::AttachedToLeavesTreeDecorator;
|
||||
@ -63,22 +65,24 @@ impl TreeDecorator {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_leaf_litter_positions(
|
||||
root_positions: &[BlockPos],
|
||||
log_positions: &[BlockPos],
|
||||
) -> Vec<BlockPos> {
|
||||
pub(super) fn get_leaf_litter_positions<'a>(
|
||||
root_positions: &'a [BlockPos],
|
||||
log_positions: &'a [BlockPos],
|
||||
) -> Cow<'a, [BlockPos]> {
|
||||
if root_positions.is_empty() {
|
||||
return log_positions.to_vec();
|
||||
return Cow::Borrowed(log_positions);
|
||||
}
|
||||
|
||||
if let (Some(root), Some(log)) = (root_positions.first(), log_positions.first())
|
||||
&& root.0.y == log.0.y
|
||||
if log_positions
|
||||
.first()
|
||||
.is_some_and(|log| root_positions[0].0.y == log.0.y)
|
||||
{
|
||||
let mut list = Vec::with_capacity(root_positions.len() + log_positions.len());
|
||||
list.extend_from_slice(log_positions);
|
||||
list.extend_from_slice(root_positions);
|
||||
return list;
|
||||
return Cow::Owned(list);
|
||||
}
|
||||
root_positions.to_vec()
|
||||
|
||||
Cow::Borrowed(root_positions)
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ impl PlaceOnGroundTreeDecorator {
|
||||
let mut l = pos.0.z;
|
||||
let mut m = pos.0.z;
|
||||
|
||||
for block_pos_2 in list {
|
||||
for block_pos_2 in list.iter() {
|
||||
if block_pos_2.0.y != i {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ pub struct SignBlockEntity {
|
||||
pub struct Text {
|
||||
pub has_glowing_text: AtomicBool,
|
||||
color: AtomicI8,
|
||||
pub messages: Arc<std::sync::Mutex<[String; 4]>>,
|
||||
pub messages: Arc<std::sync::Mutex<[Box<str>; 4]>>,
|
||||
}
|
||||
|
||||
impl Clone for Text {
|
||||
@ -160,7 +160,7 @@ impl From<Text> for NbtTag {
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|s| Self::String(s.clone().into()))
|
||||
.map(|s| Self::String(s.clone()))
|
||||
.collect(),
|
||||
);
|
||||
Self::Compound(nbt)
|
||||
@ -173,28 +173,30 @@ impl From<NbtTag> for Text {
|
||||
let nbt = tag.extract_compound().unwrap();
|
||||
let has_glowing_text = nbt.get_bool("has_glowing_text").unwrap_or(false);
|
||||
let color = nbt.get_string("color").unwrap();
|
||||
let messages: Vec<String> = nbt
|
||||
let messages: Vec<Box<str>> = nbt
|
||||
.get_list("messages")
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter_map(|tag| tag.extract_string().map(std::string::ToString::to_string))
|
||||
.filter_map(|tag| tag.extract_string().map(Box::from))
|
||||
.collect();
|
||||
let get_message =
|
||||
|i: usize| -> Box<str> { messages.get(i).cloned().unwrap_or_else(|| Box::from("")) };
|
||||
|
||||
Self {
|
||||
has_glowing_text: AtomicBool::new(has_glowing_text),
|
||||
color: AtomicI8::new(DyeColor::from(color) as i8),
|
||||
messages: Arc::new(std::sync::Mutex::new([
|
||||
// its important that we use unwrap_or since otherwise we may crash on older versions
|
||||
messages.first().unwrap_or(&String::new()).clone(),
|
||||
messages.get(1).unwrap_or(&String::new()).clone(),
|
||||
messages.get(2).unwrap_or(&String::new()).clone(),
|
||||
messages.get(3).unwrap_or(&String::new()).clone(),
|
||||
get_message(0),
|
||||
get_message(1),
|
||||
get_message(2),
|
||||
get_message(3),
|
||||
])),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Text {
|
||||
fn new(messages: [String; 4]) -> Self {
|
||||
fn new(messages: [Box<str>; 4]) -> Self {
|
||||
Self {
|
||||
has_glowing_text: AtomicBool::new(false),
|
||||
color: AtomicI8::new(DyeColor::default() as i8),
|
||||
@ -263,7 +265,7 @@ impl BlockEntity for SignBlockEntity {
|
||||
impl SignBlockEntity {
|
||||
pub const ID: &'static str = "minecraft:sign";
|
||||
#[must_use]
|
||||
pub fn new(position: BlockPos, is_front: bool, messages: [String; 4]) -> Self {
|
||||
pub fn new(position: BlockPos, is_front: bool, messages: [Box<str>; 4]) -> Self {
|
||||
Self {
|
||||
position,
|
||||
is_waxed: AtomicBool::new(false),
|
||||
|
||||
@ -9,6 +9,7 @@ use crate::net::java::{JavaClient, PacketHandlerResult};
|
||||
use crate::net::{ClientPlatform, DisconnectReason};
|
||||
use crate::net::{lan_broadcast::LANBroadcast, query, rcon::RCONServer};
|
||||
use crate::server::{Server, ticker::Ticker};
|
||||
use bytes::BytesMut;
|
||||
use plugin::server::server_command::ServerCommandEvent;
|
||||
use pumpkin_config::{AdvancedConfiguration, BasicConfiguration};
|
||||
use pumpkin_macros::send_cancellable;
|
||||
@ -18,7 +19,7 @@ use rustyline::Editor;
|
||||
use rustyline::history::FileHistory;
|
||||
use rustyline::{Config, error::ReadlineError};
|
||||
use std::collections::HashMap;
|
||||
use std::io::{Cursor, ErrorKind, IsTerminal, stdin};
|
||||
use std::io::{ErrorKind, IsTerminal, stdin};
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
|
||||
@ -418,14 +419,13 @@ impl PumpkinServer {
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(clippy::too_many_lines)]
|
||||
pub async fn unified_listener_task(
|
||||
&self,
|
||||
master_client_id_counter: &mut u64,
|
||||
tasks: &Arc<TaskTracker>,
|
||||
bedrock_clients: &Arc<Mutex<HashMap<SocketAddr, Arc<BedrockClient>>>>,
|
||||
) -> bool {
|
||||
let mut udp_buf = [0; 1496]; // Buffer for UDP receive
|
||||
let mut udp_buf = BytesMut::with_capacity(1496);
|
||||
|
||||
select! {
|
||||
// Branch for TCP connections (Java Edition)
|
||||
@ -491,7 +491,10 @@ impl PumpkinServer {
|
||||
},
|
||||
|
||||
// Branch for UDP packets (Bedrock Edition)
|
||||
udp_result = resolve_some(self.udp_socket.as_ref(), |sock: &Arc<UdpSocket>| sock.recv_from(&mut udp_buf)) => {
|
||||
udp_result = resolve_some(self.udp_socket.as_ref(), |sock: &Arc<UdpSocket>| {
|
||||
unsafe { udp_buf.set_len(1496) };
|
||||
sock.recv_from(&mut udp_buf[..])
|
||||
}) => {
|
||||
match udp_result {
|
||||
Ok((len, client_addr)) => {
|
||||
if len > 0 {
|
||||
@ -515,25 +518,20 @@ impl PumpkinServer {
|
||||
new_client
|
||||
}).clone();
|
||||
|
||||
let reader = udp_buf[..len].to_vec();
|
||||
let packet_bytes = udp_buf.split_to(len).freeze();
|
||||
udp_buf.clear();
|
||||
let server = self.server.clone();
|
||||
tasks.spawn(async move {
|
||||
client.process_packet(&server, reader).await;
|
||||
});
|
||||
|
||||
} else if let Some(sock) = self.udp_socket.as_ref() {
|
||||
let _ = BedrockClient::handle_offline_packet(
|
||||
&self.server,
|
||||
id,
|
||||
&mut Cursor::new(&udp_buf[1..len]),
|
||||
client_addr,
|
||||
sock
|
||||
).await;
|
||||
tasks.spawn(async move {
|
||||
client.process_packet(&server, packet_bytes).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => error!("UDP socket error: {e}"),
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to receive UDP packet: {e}");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Branch for the global stop signal
|
||||
|
||||
@ -106,7 +106,7 @@ pub fn authenticate(
|
||||
|
||||
pub fn validate_textures(property: &Property, config: &TextureConfig) -> Result<(), TextureError> {
|
||||
let from64 = general_purpose::STANDARD
|
||||
.decode(&property.value)
|
||||
.decode(property.value.as_bytes())
|
||||
.map_err(|e| TextureError::DecodeError(e.to_string()))?;
|
||||
let textures: ProfileTextures =
|
||||
serde_json::from_slice(&from64).map_err(|e| TextureError::JSONError(e.to_string()))?;
|
||||
|
||||
@ -229,7 +229,7 @@ impl BedrockClient {
|
||||
});
|
||||
}
|
||||
|
||||
pub async fn process_packet(self: &Arc<Self>, server: &Arc<Server>, packet: Vec<u8>) {
|
||||
pub async fn process_packet(self: &Arc<Self>, server: &Arc<Server>, packet: Bytes) {
|
||||
self.last_seen.store(std::time::Instant::now());
|
||||
if let Err(error) = self.handle_packet_payload(server, packet).await {
|
||||
error!(
|
||||
@ -501,7 +501,7 @@ impl BedrockClient {
|
||||
pub async fn handle_packet_payload(
|
||||
self: &Arc<Self>,
|
||||
server: &Arc<Server>,
|
||||
packet: Vec<u8>,
|
||||
packet: Bytes,
|
||||
) -> Result<(), Error> {
|
||||
let reader = &mut Cursor::new(packet);
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ impl JavaClient {
|
||||
match bungeecord::bungeecord_login(
|
||||
&self.address,
|
||||
&self.server_address.lock().await,
|
||||
login_start.name,
|
||||
login_start.name.into_string(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
@ -82,7 +82,7 @@ impl JavaClient {
|
||||
|
||||
let profile = GameProfile {
|
||||
id,
|
||||
name: login_start.name,
|
||||
name: login_start.name.into_string(),
|
||||
properties: ArcSwap::new(Arc::new(vec![])),
|
||||
profile_actions: None,
|
||||
};
|
||||
|
||||
@ -76,7 +76,7 @@ pub struct JavaClient {
|
||||
/// The client's configuration settings, Optional
|
||||
pub config: Mutex<Option<PlayerConfig>>,
|
||||
/// The Address used to connect to the Server, Send in the Handshake
|
||||
pub server_address: Mutex<String>,
|
||||
pub server_address: Mutex<Box<str>>,
|
||||
/// The current connection state of the client (e.g., Handshaking, Status, Play).
|
||||
pub connection_state: AtomicCell<ConnectionState>,
|
||||
/// The client's IP address.
|
||||
@ -138,7 +138,7 @@ impl JavaClient {
|
||||
id,
|
||||
gameprofile: Mutex::new(None),
|
||||
config: Mutex::new(None),
|
||||
server_address: Mutex::new(String::new()),
|
||||
server_address: Mutex::new("".into()),
|
||||
address: Mutex::new(address),
|
||||
connection_state: AtomicCell::new(ConnectionState::HandShake),
|
||||
close_token: CancellationToken::new(),
|
||||
@ -921,7 +921,7 @@ impl JavaClient {
|
||||
let payload = SCustomPayload::read(payload, &version)?;
|
||||
let event = PlayerCustomPayloadEvent::new(
|
||||
player.clone(),
|
||||
payload.channel,
|
||||
payload.channel.to_string(),
|
||||
Bytes::from(payload.data),
|
||||
);
|
||||
server.plugin_manager.fire(event).await;
|
||||
|
||||
@ -1211,7 +1211,7 @@ impl JavaClient {
|
||||
|
||||
send_cancellable! {{
|
||||
server;
|
||||
PlayerChatEvent::new(player.clone(), chat_message.message.clone(), vec![]);
|
||||
PlayerChatEvent::new(player.clone(), chat_message.message.to_string(), vec![]);
|
||||
|
||||
'after: {
|
||||
info!("<chat> {}: {}", gameprofile.name, event.message);
|
||||
|
||||
@ -80,14 +80,14 @@ fn read_game_profile(read: impl Read) -> Result<GameProfile, VelocityError> {
|
||||
.map_err(|_| VelocityError::FailedReadProfileUUID)?;
|
||||
|
||||
let name = read
|
||||
.get_string()
|
||||
.get_str()
|
||||
.map_err(|_| VelocityError::FailedReadProfileName)?;
|
||||
|
||||
let properties = read
|
||||
.get_list(|data| {
|
||||
let name = data.get_string()?;
|
||||
let value = data.get_string()?;
|
||||
let signature = data.get_option(NetworkReadExt::get_string)?;
|
||||
let name = data.get_str()?;
|
||||
let value = data.get_str()?;
|
||||
let signature = data.get_option(NetworkReadExt::get_str)?;
|
||||
|
||||
Ok(Property {
|
||||
name,
|
||||
@ -99,7 +99,7 @@ fn read_game_profile(read: impl Read) -> Result<GameProfile, VelocityError> {
|
||||
|
||||
Ok(GameProfile {
|
||||
id,
|
||||
name,
|
||||
name: name.into_string(),
|
||||
properties: ArcSwap::new(Arc::from(properties)),
|
||||
profile_actions: None,
|
||||
})
|
||||
@ -131,7 +131,7 @@ pub fn receive_velocity_plugin_response(
|
||||
));
|
||||
}
|
||||
let addr = data_without_signature
|
||||
.get_string()
|
||||
.get_str()
|
||||
.map_err(|_| VelocityError::FailedReadAddress)?;
|
||||
|
||||
let socket_addr: SocketAddr = SocketAddr::new(
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use thiserror::Error;
|
||||
|
||||
@ -60,7 +58,7 @@ pub enum PacketError {
|
||||
#[error("Missing packet lull terminator")]
|
||||
MissingNullTerminator,
|
||||
#[error("Invalid packet string body")]
|
||||
InvalidBody(FromUtf8Error),
|
||||
InvalidBody(std::str::Utf8Error),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -68,7 +66,7 @@ pub enum PacketError {
|
||||
pub struct Packet {
|
||||
id: i32,
|
||||
ptype: ServerboundPacket,
|
||||
body: String,
|
||||
body: Box<str>,
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
@ -110,8 +108,9 @@ impl Packet {
|
||||
}
|
||||
|
||||
let payload = &incoming[body_start..body_end];
|
||||
let body = String::from_utf8(payload.to_vec()).map_err(PacketError::InvalidBody)?;
|
||||
|
||||
let body = std::str::from_utf8(payload)
|
||||
.map_err(PacketError::InvalidBody)?
|
||||
.into();
|
||||
incoming.drain(0..total_packet_len);
|
||||
|
||||
Ok(Some(Self {
|
||||
|
||||
@ -82,7 +82,13 @@ const fn to_wasm_dye_color(color: InternalDyeColor) -> DyeColor {
|
||||
|
||||
fn to_wasm_sign_text(text: &InternalText) -> SignText {
|
||||
SignText {
|
||||
messages: text.messages.lock().unwrap().to_vec(),
|
||||
messages: text
|
||||
.messages
|
||||
.lock()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.map(str::into_string)
|
||||
.to_vec(),
|
||||
color: to_wasm_dye_color(text.get_color()),
|
||||
has_glowing_text: text
|
||||
.has_glowing_text
|
||||
|
||||
@ -1326,10 +1326,10 @@ impl pumpkin::plugin::player::HostPlayer for PluginHostState {
|
||||
.properties
|
||||
.load()
|
||||
.iter()
|
||||
.find(|p| p.name == "textures")
|
||||
.find(|p| p.name.as_ref() == "textures")
|
||||
.map(|p| PlayerSkin {
|
||||
value: p.value.clone(),
|
||||
signature: p.signature.clone(),
|
||||
value: p.value.to_string(),
|
||||
signature: p.signature.as_ref().map(std::string::ToString::to_string),
|
||||
}))
|
||||
}
|
||||
|
||||
@ -1341,11 +1341,11 @@ impl pumpkin::plugin::player::HostPlayer for PluginHostState {
|
||||
let player = player_from_resource(self, &player)?;
|
||||
let mut properties = (**player.gameprofile.properties.load()).clone();
|
||||
|
||||
properties.retain(|p| p.name != "textures");
|
||||
properties.retain(|p| p.name.as_ref() != "textures");
|
||||
properties.push(Property {
|
||||
name: "textures".into(),
|
||||
value: skin.value,
|
||||
signature: skin.signature,
|
||||
value: skin.value.into(),
|
||||
signature: skin.signature.map(std::convert::Into::into),
|
||||
});
|
||||
|
||||
player.gameprofile.properties.store(Arc::new(properties));
|
||||
@ -1509,7 +1509,7 @@ impl pumpkin::plugin::player::HostJavaPlayer for PluginHostState {
|
||||
.client
|
||||
.java()
|
||||
.ok_or_else(|| wasmtime::Error::msg("Not a java player"))?;
|
||||
Ok(client.server_address.lock().await.clone())
|
||||
Ok(client.server_address.lock().await.to_string())
|
||||
}
|
||||
|
||||
async fn get_settings(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user