Bedrock player joining (#1063)

Co-authored-by: unschlagbar <adrian@kuhlmann@gmx.de>
Co-authored-by: Alexander Medvedev <lilalexmed@proton.me>
Co-authored-by: unschlagbar <adrian@kuhlmann@gmx.de>
This commit is contained in:
unschlagbar
2025-07-26 17:31:00 +02:00
committed by GitHub
parent fc1a9a5bd4
commit 2e2236bf3b
245 changed files with 4412 additions and 3064 deletions

22
Cargo.lock generated
View File

@@ -2003,7 +2003,7 @@ dependencies = [
[[package]]
name = "pumpkin"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"async-trait",
"base64 0.22.1",
@@ -2048,7 +2048,7 @@ dependencies = [
[[package]]
name = "pumpkin-api-macros"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"proc-macro-error2",
"proc-macro2",
@@ -2058,7 +2058,7 @@ dependencies = [
[[package]]
name = "pumpkin-config"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"log",
"pumpkin-util",
@@ -2069,7 +2069,7 @@ dependencies = [
[[package]]
name = "pumpkin-data"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"heck",
"phf",
@@ -2085,7 +2085,7 @@ dependencies = [
[[package]]
name = "pumpkin-inventory"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"async-trait",
"crossbeam-utils",
@@ -2100,7 +2100,7 @@ dependencies = [
[[package]]
name = "pumpkin-macros"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"heck",
"proc-macro-error2",
@@ -2111,7 +2111,7 @@ dependencies = [
[[package]]
name = "pumpkin-nbt"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"bytes",
"cesu8",
@@ -2123,7 +2123,7 @@ dependencies = [
[[package]]
name = "pumpkin-protocol"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"aes",
"async-compression",
@@ -2145,7 +2145,7 @@ dependencies = [
[[package]]
name = "pumpkin-registry"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"indexmap 2.10.0",
"pumpkin-protocol",
@@ -2156,7 +2156,7 @@ dependencies = [
[[package]]
name = "pumpkin-util"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"bytes",
"colored",
@@ -2176,7 +2176,7 @@ dependencies = [
[[package]]
name = "pumpkin-world"
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
dependencies = [
"async-trait",
"bitflags",

View File

@@ -14,7 +14,7 @@ members = [
]
[workspace.package]
version = "0.1.0-dev+1.21.7"
version = "0.1.0-dev+1.21.8"
edition = "2024"
[profile.release]

View File

@@ -21,7 +21,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi
## Goals
- **Performance**: Leveraging multi-threading for maximum speed and efficiency.
- **Compatibility**: Supports the latest Java & Bedrock/Pocket Minecraft server version while adhering to Vanilla game mechanics.
- **Compatibility**: Supports the latest Java & Bedrock Minecraft server version while adhering to Vanilla game mechanics.
- **Security**: Prioritizes security by preventing known security exploits.
- **Flexibility**: Highly configurable, with the ability to disable unnecessary features.
- **Extensibility**: Provides a foundation for plugin development.

Binary file not shown.

View File

@@ -9,6 +9,8 @@ serde.workspace = true
log.workspace = true
uuid.workspace = true
#TODO Toml format is simple: make our own parser!
#This crate has 19 dependencies
toml = "0.9"
[features]

View File

@@ -6,13 +6,7 @@ use pumpkin_util::{Difficulty, GameMode, PermissionLvl};
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use std::path::PathBuf;
use std::{
env, fs,
net::{Ipv4Addr, SocketAddr},
num::NonZeroU8,
path::Path,
sync::LazyLock,
};
use std::{env, fs, num::NonZeroU8, path::Path, sync::LazyLock};
pub mod fun;
pub mod logging;
pub mod networking;
@@ -111,11 +105,11 @@ pub struct BasicConfiguration {
// Whether Java Edition Client's are Accepted
pub java_edition: bool,
/// The address and port to which the Java Edition server will bind
pub java_edition_address: SocketAddr,
// Whether Bedrock/Pocket Edition Client's are Accepted
pub java_edition_port: u16,
// Whether Bedrock Edition Client's are Accepted
pub bedrock_edition: bool,
/// The address and port to which the Bedrock/Pocket Edition server will bind
pub bedrock_edition_address: SocketAddr,
/// The address and port to which the Bedrock Edition server will bind
pub bedrock_edition_port: u16,
/// The seed for world generation.
pub seed: String,
/// The maximum number of players allowed on the server. Specifying `0` disables the limit.
@@ -164,12 +158,12 @@ impl Default for BasicConfiguration {
fn default() -> Self {
Self {
java_edition: true,
java_edition_address: SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 25565),
java_edition_port: 25565,
bedrock_edition: true,
bedrock_edition_address: SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 19132),
bedrock_edition_port: 19132,
seed: "".to_string(),
max_players: 100000,
view_distance: NonZeroU8::new(10).unwrap(),
max_players: 1000,
view_distance: NonZeroU8::new(16).unwrap(),
simulation_distance: NonZeroU8::new(10).unwrap(),
default_difficulty: Difficulty::Normal,
op_permission_level: PermissionLvl::Four,
@@ -184,7 +178,7 @@ impl Default for BasicConfiguration {
scrub_ips: true,
use_favicon: true,
favicon_path: "icon.png".to_string(),
default_level_name: "world".to_string(),
default_level_name: "World".to_string(),
allow_chat_reports: false,
white_list: false,
enforce_whitelist: false,
@@ -260,7 +254,7 @@ impl LoadConfiguration for BasicConfiguration {
fn validate(&self) {
let min = NonZeroU8::new(2).unwrap();
let max = NonZeroU8::new(32).unwrap();
let max = NonZeroU8::new(64).unwrap();
assert!(
self.view_distance.ge(&min),
@@ -268,7 +262,7 @@ impl LoadConfiguration for BasicConfiguration {
);
assert!(
self.view_distance.le(&max),
"View distance must be less than 32"
"View distance must be less than 64"
);
if self.online_mode {
assert!(

View File

@@ -289,16 +289,13 @@ pub(crate) fn build() -> TokenStream {
impl Eq for Biome {}
impl Hash for Biome {
fn hash<H>(&self, state: &mut H) where H: Hasher {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
impl<'de> Deserialize<'de> for &'static Biome {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct BiomeVisitor;
impl de::Visitor<'_> for BiomeVisitor {
@@ -308,17 +305,11 @@ pub(crate) fn build() -> TokenStream {
formatter.write_str("a biome name as a string")
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Self::Value, E> {
self.visit_str(&v)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
let biome = Biome::from_name(value.strip_prefix("minecraft:").unwrap_or(value));
biome.ok_or_else(|| E::unknown_variant(value, &["unknown biome"]))
}

View File

@@ -6,6 +6,8 @@ use serde::Deserialize;
use std::{
collections::{HashMap, HashSet},
fs,
io::{Cursor, Read},
panic,
};
use syn::{Ident, LitInt, LitStr};
@@ -149,7 +151,7 @@ impl ToTokens for PropertyStruct {
fn from_value(value: &str) -> Self {
match value {
#(#from_values),*,
_ => panic!("Invalid value: {value:?}"),
_ => panic!("Invalid value: {value}"),
}
}
@@ -255,7 +257,7 @@ impl ToTokens for BlockPropertyStruct {
match &entry.property_type {
PropertyType::Bool => quote! {
#key => {
block_props.#field_name = matches!(value, "true")
block_props.#field_name = matches!(*value, "true")
}
},
PropertyType::Enum { name } => {
@@ -323,16 +325,16 @@ impl ToTokens for BlockPropertyStruct {
Self::from_state_id(block.default_state.id, block)
}
fn to_props(&self) -> HashMap<String, String> {
HashMap::from([#(#to_props_values)*])
fn to_props(&self) -> Box<[(String, String)]> {
[#(#to_props_values)*].into()
}
fn from_props(props: HashMap<&str, &str>, block: &Block) -> Self {
fn from_props(props: &[(&str, &str)], block: &Block) -> Self {
if ![#(#block_ids),*].contains(&block.id) {
panic!("{} is not a valid block for {}", &block.name, #struct_name);
}
let mut block_props = Self::default(block);
for (key, value) in props {
match key {
match *key {
#(#from_props_values),*,
_ => panic!("Invalid key: {key}"),
}
@@ -633,8 +635,13 @@ pub struct BlockAssets {
pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=../assets/blocks.json");
println!("cargo:rerun-if-changed=../assets/bedrock_block_states.nbt");
println!("cargo:rerun-if-changed=../assets/properties.json");
let be_blocks = fs::read("../assets/bedrock_block_states.nbt").unwrap();
let mut be_blocks = Cursor::new(be_blocks);
let be_blocks = get_be_data_from_nbt(&mut be_blocks);
let blocks_assets: BlockAssets =
serde_json::from_str(&fs::read_to_string("../assets/blocks.json").unwrap())
.expect("Failed to parse blocks.json");
@@ -652,24 +659,7 @@ pub(crate) fn build() -> TokenStream {
let mut block_properties_from_props_and_name = TokenStream::new();
let mut existing_item_ids: Vec<u16> = Vec::new();
let mut constants = TokenStream::new();
// Collect unique block states to create partial block states to save memory.
let mut unique_states = Vec::new();
for block in blocks_assets.blocks.clone() {
for state in block.states.clone() {
// Check if this state is already in `unique_states` by comparing all fields except `id`.
let already_exists = unique_states.iter().any(|s: &BlockState| {
s.state_flags == state.state_flags
&& s.luminance == state.luminance
&& s.hardness == state.hardness
&& s.collision_shapes == state.collision_shapes
});
if !already_exists {
unique_states.push(state);
}
}
}
let mut block_state_to_bedrock = Vec::new();
// Used to create property `enum`s.
let mut property_enums: HashMap<String, PropertyStruct> = HashMap::new();
@@ -678,9 +668,9 @@ pub(crate) fn build() -> TokenStream {
// Mapping of a collection of property hashes -> blocks that have these properties.
let mut property_collection_map: HashMap<Vec<i32>, PropertyCollectionData> = HashMap::new();
// Validator that we have no `enum` collisions.
let mut optimized_blocks: Vec<(String, Block)> = Vec::new();
let mut optimized_blocks: Vec<Block> = Vec::new();
for block in blocks_assets.blocks.clone() {
optimized_blocks.push((block.name.clone(), block.clone()));
optimized_blocks.push(block.clone());
// Collect state IDs that have random ticks.
for state in &block.states {
@@ -752,11 +742,11 @@ pub(crate) fn build() -> TokenStream {
let id_lit = LitInt::new(&id.to_string(), Span::call_site());
block_properties_from_state_and_block_id.extend(quote! {
#id_lit => Some(Box::new(#property_name::from_state_id(state_id, &Block::#const_block_name))),
#id_lit => Box::new(#property_name::from_state_id(state_id, &Block::#const_block_name)),
});
block_properties_from_props_and_name.extend(quote! {
#id_lit => Some(Box::new(#property_name::from_props(props, &Block::#const_block_name))),
#id_lit => Box::new(#property_name::from_props(props, &Block::#const_block_name)),
});
}
@@ -789,9 +779,12 @@ pub(crate) fn build() -> TokenStream {
let mut raw_id_from_state_id_array = vec![];
let mut type_from_raw_id_array = vec![];
//let mut file = fs::File::create("../debug/debug.txt").unwrap();
// Generate constants and `match` arms for each block.
for (name, block) in optimized_blocks {
let const_ident = format_ident!("{}", const_block_name_from_block_name(&name));
for block in optimized_blocks {
let const_ident = format_ident!("{}", const_block_name_from_block_name(&block.name));
let name = &block.name;
let mut block_tokens = TokenStream::new();
block.to_tokens(&mut block_tokens);
let id_lit = LitInt::new(&block.id.to_string(), Span::call_site());
@@ -809,7 +802,35 @@ pub(crate) fn build() -> TokenStream {
#name => Self::#const_ident,
});
for state in &block.states {
let be_name = match block.name.as_str() {
"dead_bush" => "deadbush",
"tripwire" => "trip_wire",
"note_block" => "noteblock",
"powered_rail" => "golden_rail",
"cobweb" => "web",
"tall_seagrass" => "seagrass",
"wall_torch" => "torch",
"spawner" => "mob_spawner",
"snow" => "snow_layer",
"snow_block" => "snow",
name => name,
};
let (state_count, id) = *be_blocks.get(be_name).unwrap_or(&(0, 1));
for (i, state) in block.states.iter().enumerate() {
if state_count != 0 {
if state_count > i as u32 {
let start_id = id as u16 + i as u16;
block_state_to_bedrock.push((state.id, start_id))
} else {
let start_id = id as u16 + state_count as u16 - 1;
block_state_to_bedrock.push((state.id, start_id))
}
}
//else {
//file.write_all(format!("{be_name}\n").as_bytes()).unwrap();
//}
raw_id_from_state_id_array.push((state.id, id_lit.clone()));
}
@@ -828,6 +849,25 @@ pub(crate) fn build() -> TokenStream {
#id_lit,
});
}
let max_index = block_state_to_bedrock
.iter()
.map(|(index, _)| index)
.max()
.unwrap();
let mut state_to_bedrock_id = vec![quote! { 1 }; (max_index + 1) as usize];
let mut block_state_to_bedrock_t = TokenStream::new();
for (state_id, id_lit) in block_state_to_bedrock {
state_to_bedrock_id[state_id as usize] = quote! { #id_lit };
}
for id_lit in state_to_bedrock_id {
block_state_to_bedrock_t.extend(quote! {
#id_lit,
});
}
let type_from_raw_id_array = fill_array(type_from_raw_id_array);
let max_type_id = type_from_raw_id_array.len();
for type_lit in type_from_raw_id_array {
@@ -870,10 +910,10 @@ pub(crate) fn build() -> TokenStream {
fn default(block: &Block) -> Self where Self: Sized;
// Convert properties to a `Vec` of `(name, value)`
fn to_props(&self) -> HashMap<String, String>;
fn to_props(&self) -> Box<[(String, String)]>;
// Convert properties to a block state, and add them onto the default state.
fn from_props(props: HashMap<&str, &str>, block: &Block) -> Self where Self: Sized;
fn from_props(props: &[(&str, &str)], block: &Block) -> Self where Self: Sized;
}
pub trait EnumVariants {
@@ -896,46 +936,42 @@ pub(crate) fn build() -> TokenStream {
#(#block_entity_types),*
];
pub fn get_block(registry_id: &str) -> Option<&'static Block> {
let key = registry_id.strip_prefix("minecraft:").unwrap_or(registry_id);
Block::from_registry_key(key)
}
pub fn get_block_by_id(id: u16) -> &'static Block {
Block::from_id(id)
}
pub fn get_state_by_state_id(id: u16) -> &'static BlockState {
let state: &BlockState = Block::from_state_id(id).states.iter().find(|state| state.id == id).unwrap();
state
}
pub fn get_block_by_state_id(id: u16) -> &'static Block {
Block::from_state_id(id)
}
pub fn get_block_and_state_by_state_id(id: u16) -> (&'static Block, &'static BlockState) {
let block = Block::from_state_id(id);
let state: &BlockState = block.states.iter().find(|state| state.id == id).unwrap();
(block, state)
}
pub fn get_block_by_item(item_id: u16) -> Option<&'static Block> {
Block::from_item_id(item_id)
}
pub fn has_random_ticks(state_id: u16) -> bool {
matches!(state_id, #random_tick_state_ids)
}
pub fn blocks_movement(block_state: &BlockState) -> bool {
if block_state.is_solid() {
let block = get_block_by_state_id(block_state.id);
let block = Block::from_state_id(block_state.id);
return block != &Block::COBWEB && block != &Block::BAMBOO_SAPLING;
}
false
}
impl BlockState {
const STATE_ID_TO_BEDROCK: &[u16] = &[
#block_state_to_bedrock_t
];
#[doc = r" Get a block state from a state id."]
#[doc = r" If you need access to the block use `BlockState::from_id_with_block` instead."]
pub fn from_id(id: u16) -> &'static Self {
let state: &Self = Block::from_state_id(id).states.iter().find(|state| state.id == id).unwrap();
state
}
#[doc = r" Get a block state from a state id and the corresponding block."]
pub fn from_id_with_block(id: u16) -> (&'static Block, &'static BlockState) {
let block = Block::from_state_id(id);
let state: &Self = block.states.iter().find(|state| state.id == id).unwrap();
(block, state)
}
pub fn to_be_network_id(id: u16) -> u16 {
Self::STATE_ID_TO_BEDROCK[id as usize]
}
}
impl Block {
#constants
@@ -958,7 +994,13 @@ pub(crate) fn build() -> TokenStream {
Self::BLOCK_FROM_NAME_MAP.get(name)
}
#[doc = r" Try to parse a block from a raw id."]
#[doc = r" Try to get a block from a namespace prefixed name."]
pub fn from_name(name: &str) -> Option<&'static Self> {
let key = name.strip_prefix("minecraft:").unwrap_or(name);
Self::BLOCK_FROM_NAME_MAP.get(key)
}
#[doc = r" Get a block from a raw block id."]
pub const fn from_id(id: u16) -> &'static Self {
if id as usize >= Self::RAW_ID_FROM_STATE_ID.len() {
&Self::AIR
@@ -967,7 +1009,7 @@ pub(crate) fn build() -> TokenStream {
}
}
#[doc = r" Try to parse a block from a state id."]
#[doc = r" Get a block from a state id."]
pub const fn from_state_id(id: u16) -> &'static Self {
if id as usize >= Self::RAW_ID_FROM_STATE_ID.len() {
return &Self::AIR;
@@ -984,19 +1026,21 @@ pub(crate) fn build() -> TokenStream {
}
}
#[track_caller]
#[doc = r" Get the properties of the block."]
pub fn properties(&self, state_id: u16) -> Option<Box<dyn BlockProperties>> {
match self.id {
Some(match self.id {
#block_properties_from_state_and_block_id
_ => None
}
_ => return None,
})
}
#[track_caller]
#[doc = r" Get the properties of the block."]
pub fn from_properties(&self, props: HashMap<&str, &str>) -> Option<Box<dyn BlockProperties>> {
pub fn from_properties(&self, props: &[(&str, &str)]) -> Box<dyn BlockProperties> {
match self.id {
#block_properties_from_props_and_name
_ => None
_ => panic!("Invalid props")
}
}
}
@@ -1079,3 +1123,88 @@ pub(crate) fn build() -> TokenStream {
}
}
}
fn get_be_data_from_nbt<R: Read>(reader: &mut R) -> HashMap<String, (u32, u32)> {
let mut block_data: HashMap<String, (u32, u32)> = HashMap::new();
let mut current_id = 0;
while read_byte(reader) == 10 {
let len = read_varint(reader);
let mut buf = vec![0; len as usize];
reader.read_exact(&mut buf).unwrap();
let mut name = String::new();
let mut byte = read_byte(reader);
while byte != 0 {
let mut name_buf = vec![0; read_varint(reader) as usize];
reader.read_exact(&mut name_buf).unwrap();
let cp_name = String::from_utf8(name_buf).unwrap();
match cp_name.as_str() {
"name" => {
let mut name_buf = vec![0; read_varint(reader) as usize];
reader.read_exact(&mut name_buf).unwrap();
name = String::from_utf8(name_buf)
.unwrap()
.strip_prefix("minecraft:")
.unwrap()
.to_string();
}
"states" => {
let mut byte = read_byte(reader);
while byte != 0 {
let b = &mut vec![0; read_varint(reader) as usize];
reader.read_exact(b).unwrap();
match byte {
8 => {
let b = &mut vec![0; read_varint(reader) as usize];
reader.read_exact(b).unwrap();
}
3 => {
read_varint(reader);
}
1 => {
read_byte(reader);
}
_ => panic!("{}", byte),
}
byte = read_byte(reader);
}
}
"version" => {
read_varint(reader);
}
_ => panic!(),
}
byte = read_byte(reader);
}
block_data
.entry(name)
.and_modify(|(v, _)| *v += 1)
.or_insert((1, current_id));
current_id += 1;
}
block_data
}
fn read_varint<W: Read>(reader: &mut W) -> u32 {
let mut val = 0;
for i in 0..5u32 {
let byte = &mut [0];
reader.read_exact(byte).unwrap();
val |= (u32::from(byte[0]) & 0x7F) << (i * 7);
if byte[0] & 0x80 == 0 {
return val;
}
}
panic!()
}
fn read_byte<W: Read>(reader: &mut W) -> u8 {
let byte = &mut [0];
reader.read_exact(byte).unwrap_or_default();
byte[0]
}

View File

@@ -12,15 +12,15 @@ pub(crate) fn build() -> TokenStream {
for (item_id, potted_block_id) in flower_pot_transformation {
variants.extend(quote! {
#item_id => Some(#potted_block_id),
#item_id => #potted_block_id,
});
}
quote! {
#[must_use]
pub const fn get_potted_item(item_id: u16) -> Option<u16> {
pub const fn get_potted_item(item_id: u16) -> u16 {
match item_id {
#variants
_ => None,
_ => 0,
}
}
}

View File

@@ -577,11 +577,11 @@ pub(crate) fn build() -> TokenStream {
);
fluid_properties_from_state_and_name.extend(quote! {
#fluid_name => Some(Box::new(#property_name::from_state_id(state_id, &Fluid::#const_fluid_name))),
#fluid_name => Box::new(#property_name::from_state_id(state_id, &Fluid::#const_fluid_name)),
});
fluid_properties_from_props_and_name.extend(quote! {
#fluid_name => Some(Box::new(#property_name::from_props(props, &Fluid::#const_fluid_name))),
#fluid_name => Box::new(#property_name::from_props(props, &Fluid::#const_fluid_name)),
});
}
@@ -723,19 +723,21 @@ pub(crate) fn build() -> TokenStream {
}
}
#[track_caller]
#[doc = r" Get the properties of the fluid."]
pub fn properties(&self, state_id: u16) -> Option<Box<dyn FluidProperties>> {
pub fn properties(&self, state_id: u16) -> Box<dyn FluidProperties> {
match self.name {
#fluid_properties_from_state_and_name
_ => None
_ => panic!("Invalid state_id")
}
}
#[track_caller]
#[doc = r" Get the properties of the fluid."]
pub fn from_properties(&self, props: Vec<(String, String)>) -> Option<Box<dyn FluidProperties>> {
pub fn from_properties(&self, props: Vec<(String, String)>) -> Box<dyn FluidProperties> {
match self.name {
#fluid_properties_from_props_and_name
_ => None
_ => panic!("Invalid props")
}
}

View File

@@ -153,11 +153,7 @@ pub(crate) fn build() -> TokenStream {
use serde::{Serialize, Deserialize, Serializer, Deserializer};
use std::{fmt::Display, str::FromStr};
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: Display,
S: Serializer,
{
pub fn serialize<T: Display, S: Serializer>(value: &T, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&value.to_string())
}

View File

@@ -40,10 +40,7 @@ impl ToTokens for HashableF32 {
}
impl<'de> Deserialize<'de> for HashableF32 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
f32::deserialize(deserializer).map(Self)
}
}
@@ -79,10 +76,7 @@ impl ToTokens for HashableF64 {
}
impl<'de> Deserialize<'de> for HashableF64 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
f64::deserialize(deserializer).map(Self)
}
}

View File

@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, fs};
use proc_macro2::TokenStream;
use quote::{ToTokens, quote};
@@ -310,7 +310,7 @@ pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=../assets/recipes.json");
let recipes_assets: Vec<RecipeTypes> =
serde_json::from_str(include_str!("../../assets/recipes.json"))
serde_json::from_str(&fs::read_to_string("../assets/recipes.json").unwrap())
.expect("Failed to parse recipes.json");
let mut crafting_recipes = Vec::new();

View File

@@ -1,6 +1,6 @@
use pumpkin_util::math::vector3::Vector3;
use crate::block_properties::{COLLISION_SHAPES, Instrument, get_block_by_state_id};
use crate::block_properties::{COLLISION_SHAPES, Instrument};
use crate::{Block, BlockDirection, CollisionShape};
#[derive(Debug)]
@@ -93,10 +93,6 @@ impl BlockState {
}
}
pub fn block(&self) -> &'static Block {
get_block_by_state_id(self.id)
}
pub fn get_block_collision_shapes(&self) -> Vec<CollisionShape> {
self.collision_shapes
.iter()
@@ -110,7 +106,7 @@ impl BlockState {
.iter()
.map(|&id| COLLISION_SHAPES[id as usize])
.collect();
let block = get_block_by_state_id(self.id);
let block = Block::from_state_id(self.id);
if block.properties(self.id).and_then(|properties| {
properties
.to_props()

View File

@@ -1,6 +1,5 @@
use crate::{
BlockState, BlockStateRef,
block_properties::get_state_by_state_id,
tag::{RegistryKey, Tagable},
};
use pumpkin_util::{
@@ -71,7 +70,7 @@ impl Block {
self.properties(state_id).is_some_and(|properties| {
properties
.to_props()
.iter()
.into_iter()
.any(|(key, value)| key == "waterlogged" && value == "true")
})
}

View File

@@ -1,6 +1,6 @@
use std::any::Any;
use std::sync::Arc;
use std::sync::atomic::AtomicU8;
use std::sync::atomic::{AtomicU8, Ordering};
use super::recipes::{RecipeFinderScreenHandler, RecipeInputInventory};
use crate::crafting::crafting_inventory::CraftingInventory;
@@ -333,8 +333,7 @@ impl Slot for ResultSlot {
}
fn set_id(&self, id: usize) {
self.id
.store(id as u8, std::sync::atomic::Ordering::Relaxed);
self.id.store(id as u8, Ordering::Relaxed);
}
async fn on_quick_move_crafted(&self, _stack: ItemStack, _stack_prev: ItemStack) {

View File

@@ -9,7 +9,7 @@ use pumpkin_world::item::ItemStack;
use std::array::from_fn;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::atomic::AtomicU8;
use std::sync::atomic::{AtomicU8, Ordering};
use tokio::sync::Mutex;
#[derive(Debug)]
@@ -417,15 +417,13 @@ impl Inventory for PlayerInventory {
impl PlayerInventory {
pub fn set_selected_slot(&self, slot: u8) {
if Self::is_valid_hotbar_index(slot as usize) {
self.selected_slot
.store(slot, std::sync::atomic::Ordering::Relaxed);
self.selected_slot.store(slot, Ordering::Relaxed);
} else {
panic!("Invalid hotbar slot: {slot}");
}
}
pub fn get_selected_slot(&self) -> u8 {
self.selected_slot
.load(std::sync::atomic::Ordering::Relaxed)
self.selected_slot.load(Ordering::Relaxed)
}
}

View File

@@ -1,7 +1,10 @@
#![warn(unused)]
use std::{
fmt::Debug,
sync::{Arc, atomic::AtomicU8},
sync::{
Arc,
atomic::{AtomicU8, Ordering},
},
time::Duration,
};
@@ -219,8 +222,7 @@ impl Slot for NormalSlot {
}
fn set_id(&self, id: usize) {
self.id
.store(id as u8, std::sync::atomic::Ordering::Relaxed);
self.id.store(id as u8, Ordering::Relaxed);
}
async fn mark_dirty(&self) {
@@ -259,8 +261,7 @@ impl Slot for ArmorSlot {
}
fn set_id(&self, id: usize) {
self.id
.store(id as u8, std::sync::atomic::Ordering::Relaxed);
self.id.store(id as u8, Ordering::Relaxed);
}
async fn get_max_item_count(&self) -> u8 {

View File

@@ -3,15 +3,13 @@ use proc_macro::TokenStream;
use proc_macro_error2::{abort, abort_call_site, proc_macro_error};
use quote::quote;
use syn::spanned::Spanned;
use syn::{self};
use syn::{self, Attribute, Type};
use syn::{
Block, Expr, Field, Fields, ItemStruct, Stmt,
parse::{Nothing, Parser},
parse_macro_input,
};
extern crate proc_macro;
#[proc_macro_derive(Event)]
pub fn event(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemStruct);
@@ -183,10 +181,9 @@ pub fn pumpkin_block(input: TokenStream, item: TokenStream) -> TokenStream {
let input_string = input.to_string();
let packet_name = input_string.trim_matches('"');
let packet_name_split: Vec<&str> = packet_name.split(":").collect();
let namespace = packet_name_split[0];
let id = packet_name_split[1];
let (namespace, id) = packet_name
.split_once(":")
.unwrap_or_else(|| abort!(packet_name, "A namespace is required!"));
let item: proc_macro2::TokenStream = item.into();
@@ -352,3 +349,143 @@ pub fn block_property(input: TokenStream, item: TokenStream) -> TokenStream {
code.into()
}
#[rustfmt::skip]
#[proc_macro_derive(PacketWrite, attributes(serial))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as syn::DeriveInput);
let name = &input.ident;
let fields = if let syn::Data::Struct(data) = &input.data {
data.fields.iter().map(|f| {
let ident = f.ident.as_ref().unwrap();
let (is_big_endian, no_prefix) = check_serial_attributes(&f.attrs);
let is_vec = is_vec(&f.ty);
if is_vec && !no_prefix {
// Vec with prefix: write VarUInt length, then data
if is_big_endian {
quote! {
crate::codec::var_uint::VarUInt(self.#ident.len() as u32).write(writer)?;
self.#ident.write_be(writer)?;
}
} else {
quote! {
crate::codec::var_uint::VarUInt(self.#ident.len() as u32).write(writer)?;
self.#ident.write(writer)?;
}
}
} else {
// Non-Vec or Vec with no_prefix: write directly
if is_big_endian {
quote! {
self.#ident.write_be(writer)?;
}
} else {
quote! {
self.#ident.write(writer)?;
}
}
}
})
} else {
unimplemented!()
};
let expanded = quote! {
impl PacketWrite for #name {
fn write<W: std::io::Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
#(#fields)*
Ok(())
}
}
};
expanded.into()
}
#[rustfmt::skip]
#[proc_macro_derive(PacketRead, attributes(serial))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as syn::DeriveInput);
let name = &input.ident;
let fields = if let syn::Data::Struct(data) = &input.data {
data.fields.iter().map(|f| {
let ident = f.ident.as_ref().unwrap();
let (is_big_endian, no_prefix) = check_serial_attributes(&f.attrs);
let is_vec = is_vec(&f.ty);
if is_vec && !no_prefix {
// Vec with prefix: read VarUInt length, then data
quote! {
#ident: {
let len = crate::codec::var_uint::VarUInt::read(reader)?.0 as usize;
let mut buf = vec![0u8; len];
reader.read_exact(&mut buf)?;
buf
}
}
} else {
// Non-Vec or Vec with no_prefix: read directly
if is_big_endian {
quote! {
#ident: PacketRead::read_be(reader)?
}
} else {
quote! {
#ident: PacketRead::read(reader)?
}
}
}
})
} else {
unimplemented!()
};
let expanded = quote! {
impl PacketRead for #name {
fn read<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
Ok(Self {
#(#fields),*
})
}
}
};
expanded.into()
}
fn check_serial_attributes(attrs: &[Attribute]) -> (bool, bool) {
let mut is_big_endian = false;
let mut no_prefix = false;
for attr in attrs.iter() {
if attr.path().is_ident("serial") {
let _ = attr.parse_nested_meta(|meta| {
if meta.path.is_ident("big_endian") {
is_big_endian = true;
} else if meta.path.is_ident("no_prefix") {
no_prefix = true;
}
Ok(())
});
}
}
(is_big_endian, no_prefix)
}
fn is_vec(ty: &Type) -> bool {
if let Type::Path(type_path) = ty {
type_path
.path
.segments
.iter()
.last()
.map(|segment| segment.ident == "Vec")
.unwrap_or(false)
} else {
false
}
}

View File

@@ -19,10 +19,7 @@ impl NbtCompound {
}
}
pub fn skip_content<R>(reader: &mut NbtReadHelper<R>) -> Result<(), Error>
where
R: Read,
{
pub fn skip_content<R: Read>(reader: &mut NbtReadHelper<R>) -> Result<(), Error> {
loop {
let tag_id = match reader.get_u8_be() {
Ok(id) => id,
@@ -53,10 +50,9 @@ impl NbtCompound {
Ok(())
}
pub fn deserialize_content<R>(reader: &mut NbtReadHelper<R>) -> Result<NbtCompound, Error>
where
R: Read,
{
pub fn deserialize_content<R: Read>(
reader: &mut NbtReadHelper<R>,
) -> Result<NbtCompound, Error> {
let mut compound = NbtCompound::new();
loop {
@@ -88,10 +84,7 @@ impl NbtCompound {
Ok(compound)
}
pub fn serialize_content<W>(&self, w: &mut WriteAdaptor<W>) -> Result<(), Error>
where
W: Write,
{
pub fn serialize_content<W: Write>(&self, w: &mut WriteAdaptor<W>) -> Result<(), Error> {
for (name, tag) in &self.child_tags {
w.write_u8_be(tag.get_type_id())?;
NbtTag::String(name.clone()).serialize_data(w)?;
@@ -183,7 +176,7 @@ impl NbtCompound {
self.get(name).and_then(|tag| tag.extract_bool())
}
pub fn get_string(&self, name: &str) -> Option<&String> {
pub fn get_string(&self, name: &str) -> Option<&str> {
self.get(name).and_then(|tag| tag.extract_string())
}
@@ -243,10 +236,7 @@ impl AsRef<NbtCompound> for NbtCompound {
}
impl Serialize for NbtCompound {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeMap;
let mut map = serializer.serialize_map(Some(self.child_tags.len()))?;
for (key, value) in &self.child_tags {
@@ -257,10 +247,7 @@ impl Serialize for NbtCompound {
}
impl<'de> Deserialize<'de> for NbtCompound {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct CompoundVisitor;
impl<'de> serde::de::Visitor<'de> for CompoundVisitor {
@@ -270,10 +257,10 @@ impl<'de> Deserialize<'de> for NbtCompound {
formatter.write_str("an NBT compound")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
fn visit_map<A: serde::de::MapAccess<'de>>(
self,
mut map: A,
) -> Result<Self::Value, A::Error> {
let mut compound = NbtCompound::new();
while let Some((key, value)) = map.next_entry::<String, NbtTag>()? {
compound.put(&key, value);

View File

@@ -81,19 +81,13 @@ impl<R: Read> Deserializer<R> {
}
/// Deserializes struct using Serde Deserializer from normal NBT
pub fn from_bytes<'a, T>(r: impl Read) -> Result<T>
where
T: Deserialize<'a>,
{
pub fn from_bytes<'a, T: Deserialize<'a>>(r: impl Read) -> Result<T> {
let mut deserializer = Deserializer::new(r, true);
T::deserialize(&mut deserializer)
}
/// Deserializes struct using Serde Deserializer from network NBT
pub fn from_bytes_unnamed<'a, T>(r: impl Read) -> Result<T>
where
T: Deserialize<'a>,
{
pub fn from_bytes_unnamed<'a, T: Deserialize<'a>>(r: impl Read) -> Result<T> {
let mut deserializer = Deserializer::new(r, false);
T::deserialize(&mut deserializer)
}
@@ -106,10 +100,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
bytes newtype_struct byte_buf
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let Some(tag) = self.tag_to_deserialize_stack.pop() else {
return Err(Error::SerdeError("Ignoring nothing!".to_string()));
};
@@ -118,10 +109,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
visitor.visit_unit()
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let Some(tag_to_deserialize) = self.tag_to_deserialize_stack.pop() else {
return Err(Error::SerdeError(
"The top level must be a component (e.g. a struct)".to_string(),
@@ -170,10 +158,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
}
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if self.in_list {
let value = self.input.get_u8_be()?;
visitor.visit_u8::<Error>(value)
@@ -184,37 +169,25 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
}
}
fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_u16<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
Err(Error::UnsupportedType(
"u16; NBT only supports signed values".to_string(),
))
}
fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_u32<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
Err(Error::UnsupportedType(
"u32; NBT only supports signed values".to_string(),
))
}
fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_u64<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
Err(Error::UnsupportedType(
"u64; NBT only supports signed values".to_string(),
))
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if let Some(tag_id) = self.tag_to_deserialize_stack.last() {
if *tag_id == BYTE_ID {
let value = self.input.get_u8_be()?;
@@ -236,31 +209,22 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
}
}
fn deserialize_enum<V>(
fn deserialize_enum<V: Visitor<'de>>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
) -> Result<V::Value> {
let variant = get_nbt_string(&mut self.input)?;
visitor.visit_enum(variant.into_deserializer())
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
// None is not encoded, so no need for it
visitor.visit_some(self)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if let Some(tag_id) = self.tag_to_deserialize_stack.pop() {
if tag_id != COMPOUND_ID {
return Err(Error::SerdeError(format!(
@@ -288,22 +252,16 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
Ok(value)
}
fn deserialize_struct<V>(
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
) -> Result<V::Value> {
self.deserialize_map(visitor)
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let str = get_nbt_string(&mut self.input)?;
visitor.visit_string(str)
}
@@ -320,10 +278,7 @@ struct CompoundAccess<'a, R: Read> {
impl<'de, R: Read> MapAccess<'de> for CompoundAccess<'_, R> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
let tag = self.de.input.get_u8_be()?;
self.de.tag_to_deserialize_stack.push(tag);
@@ -334,10 +289,7 @@ impl<'de, R: Read> MapAccess<'de> for CompoundAccess<'_, R> {
seed.deserialize(MapKey { de: self.de }).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value> {
let result = seed.deserialize(&mut *self.de);
self.de.key_stack.pop();
result
@@ -351,10 +303,7 @@ struct MapKey<'a, R: Read> {
impl<'de, R: Read> de::Deserializer<'de> for MapKey<'_, R> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let key = get_nbt_string(&mut self.de.input)?;
self.de.key_stack.push(key.clone());
visitor.visit_string(key)
@@ -379,10 +328,7 @@ impl<'de, R: Read> SeqAccess<'de> for ListAccess<'_, R> {
Some(self.remaining_values)
}
fn next_element_seed<E>(&mut self, seed: E) -> Result<Option<E::Value>>
where
E: DeserializeSeed<'de>,
{
fn next_element_seed<E: DeserializeSeed<'de>>(&mut self, seed: E) -> Result<Option<E::Value>> {
if self.remaining_values == 0 {
return Ok(None);
}

View File

@@ -83,10 +83,7 @@ impl Nbt {
}
}
pub fn read<R>(reader: &mut NbtReadHelper<R>) -> Result<Nbt, Error>
where
R: Read,
{
pub fn read<R: Read>(reader: &mut NbtReadHelper<R>) -> Result<Nbt, Error> {
let tag_type_id = reader.get_u8_be()?;
if tag_type_id != COMPOUND_ID {
@@ -100,10 +97,7 @@ impl Nbt {
}
/// Reads an NBT tag that doesn't contain the name of the root `Compound`.
pub fn read_unnamed<R>(reader: &mut NbtReadHelper<R>) -> Result<Nbt, Error>
where
R: Read,
{
pub fn read_unnamed<R: Read>(reader: &mut NbtReadHelper<R>) -> Result<Nbt, Error> {
let tag_type_id = reader.get_u8_be()?;
if tag_type_id != COMPOUND_ID {
@@ -195,11 +189,10 @@ pub(crate) const NBT_BYTE_ARRAY_TAG: &str = "__nbt_byte_array";
macro_rules! impl_array {
($name:ident, $variant:expr) => {
pub fn $name<T, S>(input: T, serializer: S) -> Result<S::Ok, S::Error>
where
T: serde::Serialize,
S: serde::Serializer,
{
pub fn $name<T: serde::Serialize, S: serde::Serializer>(
input: T,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_newtype_variant(NBT_ARRAY_TAG, 0, $variant, &input)
}
};

View File

@@ -65,11 +65,7 @@ pub fn write_gzip_compound_tag_to_bytes(compound: &NbtCompound) -> Result<Vec<u8
/// # Returns
///
/// A Result containing either the deserialized type or an Error
pub fn from_gzip_bytes<'a, T, R>(input: R) -> Result<T, Error>
where
T: serde::Deserialize<'a>,
R: Read,
{
pub fn from_gzip_bytes<'a, T: serde::Deserialize<'a>, R: Read>(input: R) -> Result<T, Error> {
// Create a GZip decoder and directly use it for deserialization
let decoder = GzDecoder::new(input);
deserializer::from_bytes(decoder)
@@ -85,11 +81,7 @@ where
/// # Returns
///
/// A Result indicating success or an Error
pub fn to_gzip_bytes<T, W>(value: &T, output: W) -> Result<(), Error>
where
T: serde::Serialize,
W: Write,
{
pub fn to_gzip_bytes<T: serde::Serialize, W: Write>(value: &T, output: W) -> Result<(), Error> {
// Create a GZip encoder that writes to the output
let encoder = GzEncoder::new(output, Compression::default());
@@ -98,10 +90,7 @@ where
}
/// Convenience function that returns compressed bytes
pub fn to_gzip_bytes_vec<T>(value: &T) -> Result<Vec<u8>, Error>
where
T: serde::Serialize,
{
pub fn to_gzip_bytes_vec<T: serde::Serialize>(value: &T) -> Result<Vec<u8>, Error> {
let mut buffer = Vec::new();
to_gzip_bytes(value, &mut buffer)?;
Ok(buffer)
@@ -157,7 +146,7 @@ mod tests {
assert_eq!(read_compound.get_double("double_value"), Some(123456.789));
assert_eq!(read_compound.get_bool("bool_value"), Some(true));
assert_eq!(
read_compound.get_string("string_value").map(String::as_str),
read_compound.get_string("string_value"),
Some("test string")
);

View File

@@ -142,29 +142,20 @@ impl<W: Write> Serializer<W> {
}
/// Serializes struct using Serde Serializer to unnamed (network) NBT
pub fn to_bytes_unnamed<T>(value: &T, w: impl Write) -> Result<()>
where
T: Serialize,
{
pub fn to_bytes_unnamed<T: Serialize>(value: &T, w: impl Write) -> Result<()> {
let mut serializer = Serializer::new(w, None);
value.serialize(&mut serializer)?;
Ok(())
}
/// Serializes struct using Serde Serializer to normal NBT
pub fn to_bytes_named<T>(value: &T, name: String, w: impl Write) -> Result<()>
where
T: Serialize,
{
pub fn to_bytes_named<T: Serialize>(value: &T, name: String, w: impl Write) -> Result<()> {
let mut serializer = Serializer::new(w, Some(name));
value.serialize(&mut serializer)?;
Ok(())
}
pub fn to_bytes<T>(value: &T, w: impl Write) -> Result<()>
where
T: Serialize,
{
pub fn to_bytes<T: Serialize>(value: &T, w: impl Write) -> Result<()> {
to_bytes_named(value, String::new(), w)
}
@@ -287,10 +278,7 @@ impl<W: Write> ser::Serializer for &mut Serializer<W> {
Ok(())
}
fn serialize_some<T>(self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<()> {
value.serialize(self)
}
@@ -312,23 +300,21 @@ impl<W: Write> ser::Serializer for &mut Serializer<W> {
Ok(())
}
fn serialize_newtype_struct<T>(self, _name: &'static str, _value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
_name: &'static str,
_value: &T,
) -> Result<()> {
Err(Error::UnsupportedType("newtype struct".to_string()))
}
fn serialize_newtype_variant<T>(
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<()>
where
T: ?Sized + Serialize,
{
) -> Result<()> {
if name == NBT_ARRAY_TAG {
let name = match self.state {
State::Named(ref name) => name.clone(),
@@ -443,10 +429,10 @@ impl<W: Write> ser::SerializeTuple for &mut Serializer<W> {
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> std::result::Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_element<T: ?Sized + Serialize>(
&mut self,
value: &T,
) -> std::result::Result<(), Self::Error> {
value.serialize(&mut **self)?;
self.state = State::CheckedListElement;
Ok(())
@@ -461,10 +447,7 @@ impl<W: Write> ser::SerializeSeq for &mut Serializer<W> {
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
value.serialize(&mut **self)?;
self.state = State::ListElement;
Ok(())
@@ -479,10 +462,11 @@ impl<W: Write> ser::SerializeStruct for &mut Serializer<W> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<()> {
self.state = State::Named(key.to_string());
value.serialize(&mut **self)
}
@@ -497,18 +481,18 @@ impl<W: Write> ser::SerializeMap for &mut Serializer<W> {
type Ok = ();
type Error = Error;
fn serialize_key<T>(&mut self, key: &T) -> std::result::Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_key<T: ?Sized + Serialize>(
&mut self,
key: &T,
) -> std::result::Result<(), Self::Error> {
self.state = State::MapKey;
key.serialize(&mut **self)
}
fn serialize_value<T>(&mut self, value: &T) -> std::result::Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_value<T: ?Sized + Serialize>(
&mut self,
value: &T,
) -> std::result::Result<(), Self::Error> {
value.serialize(&mut **self)
}

View File

@@ -32,19 +32,13 @@ impl NbtTag {
unsafe { *(self as *const Self as *const u8) }
}
pub fn serialize<W>(&self, w: &mut WriteAdaptor<W>) -> serializer::Result<()>
where
W: Write,
{
pub fn serialize<W: Write>(&self, w: &mut WriteAdaptor<W>) -> serializer::Result<()> {
w.write_u8_be(self.get_type_id())?;
self.serialize_data(w)?;
Ok(())
}
pub fn serialize_data<W>(&self, w: &mut WriteAdaptor<W>) -> serializer::Result<()>
where
W: Write,
{
pub fn serialize_data<W: Write>(&self, w: &mut WriteAdaptor<W>) -> serializer::Result<()> {
match self {
NbtTag::End => {}
NbtTag::Byte(byte) => w.write_i8_be(*byte)?,
@@ -114,18 +108,12 @@ impl NbtTag {
Ok(())
}
pub fn deserialize<R>(reader: &mut NbtReadHelper<R>) -> Result<NbtTag, Error>
where
R: Read,
{
pub fn deserialize<R: Read>(reader: &mut NbtReadHelper<R>) -> Result<NbtTag, Error> {
let tag_id = reader.get_u8_be()?;
Self::deserialize_data(reader, tag_id)
}
pub fn skip_data<R>(reader: &mut NbtReadHelper<R>, tag_id: u8) -> Result<(), Error>
where
R: Read,
{
pub fn skip_data<R: Read>(reader: &mut NbtReadHelper<R>, tag_id: u8) -> Result<(), Error> {
match tag_id {
END_ID => Ok(()),
BYTE_ID => reader.skip_bytes(1),
@@ -179,10 +167,10 @@ impl NbtTag {
}
}
pub fn deserialize_data<R>(reader: &mut NbtReadHelper<R>, tag_id: u8) -> Result<NbtTag, Error>
where
R: Read,
{
pub fn deserialize_data<R: Read>(
reader: &mut NbtReadHelper<R>,
tag_id: u8,
) -> Result<NbtTag, Error> {
match tag_id {
END_ID => Ok(NbtTag::End),
BYTE_ID => {
@@ -324,7 +312,7 @@ impl NbtTag {
}
}
pub fn extract_string(&self) -> Option<&String> {
pub fn extract_string(&self) -> Option<&str> {
match self {
NbtTag::String(string) => Some(string),
_ => None,
@@ -393,10 +381,7 @@ impl From<bool> for NbtTag {
}
impl Serialize for NbtTag {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
NbtTag::End => serializer.serialize_unit(),
NbtTag::Byte(v) => serializer.serialize_i8(*v),
@@ -444,10 +429,7 @@ impl Serialize for NbtTag {
}
impl<'de> Deserialize<'de> for NbtTag {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct NbtTagVisitor;
impl<'de> serde::de::Visitor<'de> for NbtTagVisitor {
@@ -485,17 +467,14 @@ impl<'de> Deserialize<'de> for NbtTag {
Ok(NbtTag::Double(v))
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
Ok(NbtTag::String(v.to_string()))
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
fn visit_seq<A: serde::de::SeqAccess<'de>>(
self,
mut seq: A,
) -> Result<Self::Value, A::Error> {
let mut vec = Vec::new();
while let Some(value) = seq.next_element()? {
vec.push(value);
@@ -503,10 +482,10 @@ impl<'de> Deserialize<'de> for NbtTag {
Ok(NbtTag::List(vec))
}
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
fn visit_map<A: serde::de::MapAccess<'de>>(
self,
map: A,
) -> Result<Self::Value, A::Error> {
Ok(NbtTag::Compound(NbtCompound::deserialize(
serde::de::value::MapAccessDeserializer::new(map),
)?))

View File

@@ -1,9 +1,10 @@
use std::io::{Error, Read, Write};
use pumpkin_macros::packet;
use crate::{
ClientPacket, ServerPacket,
codec::u24::U24,
ser::{NetworkReadExt, NetworkWriteExt},
codec::u24,
serial::{PacketRead, PacketWrite},
};
#[packet(0xC0)]
@@ -15,54 +16,42 @@ impl Ack {
pub fn new(sequences: Vec<u32>) -> Self {
Self { sequences }
}
}
impl Ack {
fn write_range(
start: u32,
end: u32,
mut write: impl std::io::Write,
) -> Result<(), crate::ser::WritingError> {
fn write_range<W: Write>(start: u32, end: u32, writer: &mut W) -> Result<(), Error> {
if start == end {
write.write_u8(1)?;
U24::encode(&U24(start), &mut write)?;
1u8.write(writer)?;
u24(start).write(writer)
} else {
write.write_u8(0)?;
U24::encode(&U24(start), &mut write)?;
U24::encode(&U24(end), &mut write)?;
0u8.write(writer)?;
u24(start).write(writer)?;
u24(end).write(writer)
}
Ok(())
}
}
impl ServerPacket for Ack {
fn read(mut read: impl std::io::Read) -> Result<Self, crate::ser::ReadingError> {
let size = read.get_u16_be()?;
pub fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let size = u16::read_be(reader)?;
// TODO: check size
let mut sequences = Vec::with_capacity(size as usize);
for _ in 0..size {
let single = read.get_bool()?;
let single = bool::read(reader)?;
if single {
sequences.push(U24::decode(&mut read)?.0);
sequences.push(u24::read(reader)?.0);
} else {
let start = U24::decode(&mut read)?;
let end = U24::decode(&mut read)?;
for i in start.0..end.0 {
let start = u24::read(reader)?.0;
let end = u24::read(reader)?.0;
for i in start..end {
sequences.push(i);
}
}
}
Ok(Self { sequences })
}
}
impl ClientPacket for Ack {
fn write_packet_data(
&self,
mut write: impl std::io::Write,
) -> Result<(), crate::ser::WritingError> {
let mut buffer = Vec::new();
let mut count = 0;
pub fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
0xC0u8.write(writer)?;
let mut count: u16 = 0;
let mut buf = Vec::new();
let mut start = self.sequences[0];
let mut end = start;
@@ -70,18 +59,15 @@ impl ClientPacket for Ack {
if seq == end + 1 {
end = seq
} else {
Self::write_range(start, end, &mut buffer)?;
Self::write_range(start, end, &mut buf)?;
count += 1;
start = seq;
end = seq;
}
}
Self::write_range(start, end, &mut buffer)?;
Self::write_range(start, end, &mut buf)?;
count += 1;
write.write_u16_be(count)?;
write.write_slice(&buffer)?;
Ok(())
count.write_be(writer)?;
writer.write_all(&buf)
}
}

View File

@@ -0,0 +1,10 @@
use pumpkin_macros::packet;
use crate::{codec::var_int::VarInt, serial::PacketWrite};
#[derive(PacketWrite)]
#[packet(70)]
pub struct CChunkRadiusUpdate {
// https://mojang.github.io/bedrock-protocol-docs/html/ChunkRadiusUpdatedPacket.html
pub chunk_radius: VarInt,
}

View File

@@ -0,0 +1,16 @@
use pumpkin_macros::packet;
use crate::{
codec::{bedrock_block_pos::NetworkPos, var_long::VarLong},
serial::PacketWrite,
};
#[derive(PacketWrite)]
#[packet(46)]
pub struct CContainerOpen {
// https://mojang.github.io/bedrock-protocol-docs/html/ContainerOpenPacket.html
pub container_id: u8,
pub container_type: u8,
pub position: NetworkPos,
pub target_entity_id: VarLong,
}

View File

@@ -0,0 +1,54 @@
use std::io::{Error, Write};
use pumpkin_macros::packet;
use crate::{
bedrock::network_item::NetworkItemDescriptor, codec::var_uint::VarUInt, serial::PacketWrite,
};
#[packet(145)]
pub struct CreativeContent<'a> {
// https://mojang.github.io/bedrock-protocol-docs/html/CreativeContentPacket.html
pub groups: &'a [Group],
pub entries: &'a [Entry],
}
impl PacketWrite for CreativeContent<'_> {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
VarUInt(self.groups.len() as _).write(writer)?;
for group in self.groups {
group.write(writer)?;
}
VarUInt(self.entries.len() as _).write(writer)?;
for entry in self.entries {
entry.write(writer)?;
}
Ok(())
}
}
#[repr(i32)]
#[allow(unused)]
enum CreativeCategory {
Construction = 1,
Nature = 2,
Equipment = 3,
Items = 4,
CommandOnly = 5,
Undefined = 6,
}
#[derive(PacketWrite)]
pub struct Group {
pub creative_category: i32,
pub name: String,
pub icon_item: NetworkItemDescriptor,
}
#[derive(PacketWrite)]
pub struct Entry {
pub id: VarUInt,
pub item: NetworkItemDescriptor,
pub group_index: VarUInt,
}

View File

@@ -0,0 +1,36 @@
use pumpkin_macros::packet;
use std::io::{Error, Write};
use crate::{codec::var_int::VarInt, serial::PacketWrite};
#[packet(5)]
pub struct CDisconnectPlayer {
// https://mojang.github.io/bedrock-protocol-docs/html/DisconnectPacket.html
pub reason: VarInt,
pub skip_message: bool,
pub message: String,
pub filtered_message: String,
}
impl CDisconnectPlayer {
pub fn new(reason: i32, message: String) -> Self {
Self {
reason: VarInt(reason),
skip_message: message.is_empty(),
message,
filtered_message: String::new(),
}
}
}
impl PacketWrite for CDisconnectPlayer {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.reason.write(writer)?;
self.skip_message.write(writer)?;
if !self.skip_message {
self.message.write(writer)?;
self.filtered_message.write(writer)?;
}
Ok(())
}
}

View File

@@ -1,15 +1,14 @@
use pumpkin_macros::packet;
use serde::Serialize;
use crate::codec::var_uint::VarUInt;
use crate::{codec::var_uint::VarUInt, serial::PacketWrite};
#[derive(Serialize, Default)]
#[derive(PacketWrite, Default)]
#[packet(0x48)]
pub struct CGamerulesChanged {
pub rule_data: GameRules,
}
#[derive(Serialize, Default)]
#[derive(PacketWrite, Default)]
pub struct GameRules {
// TODO https://mojang.github.io/bedrock-protocol-docs/html/GameRulesChangedPacketData.html
pub list_size: VarUInt,

View File

@@ -0,0 +1,18 @@
use pumpkin_macros::packet;
use crate::{
bedrock::network_item::NetworkItemStackDescriptor, codec::var_uint::VarUInt,
serial::PacketWrite,
};
#[derive(PacketWrite)]
#[packet(49)]
pub struct CInventoryContent {
// https://mojang.github.io/bedrock-protocol-docs/html/InventoryContentPacket.html
pub inventory_id: VarUInt,
pub slots: Vec<NetworkItemStackDescriptor>,
pub container_name: u8,
pub dynamic_id: Option<u32>,
/// Use NetworkItemDescriptor if none
pub storage_item: NetworkItemStackDescriptor,
}

View File

@@ -0,0 +1,79 @@
use std::io::{Error, Write};
use pumpkin_macros::packet;
use pumpkin_world::chunk::{ChunkData, palette::NetworkPalette};
use crate::{
codec::{var_int::VarInt, var_uint::VarUInt},
serial::PacketWrite,
};
const VERSION: u8 = 9;
#[packet(58)]
pub struct CLevelChunk<'a> {
// https://mojang.github.io/bedrock-protocol-docs/html/LevelChunkPacket.html
pub dimension: i32,
pub cache_enabled: bool,
// https://gist.github.com/Tomcc/a96af509e275b1af483b25c543cfbf37
// https://github.com/Mojang/bedrock-protocol-docs/blob/main/additional_docs/SubChunk%20Request%20System%20v1.18.10.md
pub chunk: &'a ChunkData,
}
impl<'a> PacketWrite for CLevelChunk<'a> {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
VarInt(self.chunk.position.x).write(writer)?;
VarInt(self.chunk.position.y).write(writer)?;
VarInt(self.dimension).write(writer)?;
let sub_chunk_count = self.chunk.section.sections.len() as u32;
VarUInt(sub_chunk_count).write(writer)?;
self.cache_enabled.write(writer)?;
let mut chunk_data = Vec::new();
let data_write = &mut chunk_data;
// Blocks
for (i, sub_chunk) in self.chunk.section.sections.iter().enumerate() {
// Version 9
// [version:byte][num_storages:byte][sub_chunk_index:byte][block storage1]...[blockStorageN]
let num_storages = 1;
data_write.write_all(&[VERSION, num_storages, ((i as i8) - 4) as u8])?;
let network_repr = sub_chunk.block_states.convert_be_network();
(network_repr.bits_per_entry << 1 | 1).write(data_write)?;
for data in network_repr.packed_data.iter() {
data.write(data_write)?;
}
match network_repr.palette {
NetworkPalette::Single(id) => {
VarInt(id as i32).write(data_write)?;
}
NetworkPalette::Indirect(palette) => {
VarInt(palette.len() as i32).write(data_write)?;
for id in palette {
VarInt(id as i32).write(data_write)?;
}
}
NetworkPalette::Direct => (),
}
}
// Biomes
for i in 0..sub_chunk_count {
let num_storages = 1;
data_write.write_all(&[VERSION, num_storages, ((i as i8) - 4) as u8])?;
for _ in 0..num_storages {
1u8.write(data_write)?;
VarInt(0).write(data_write)?;
}
}
data_write.write_all(&[0])?;
VarUInt(chunk_data.len() as u32).write(writer)?;
writer.write_all(&chunk_data)
}
}

View File

@@ -1,8 +1,20 @@
pub mod chunk_radius_update;
pub mod container_open;
pub mod creative_content;
pub mod disconnect_player;
pub mod gamerules_changed;
pub mod handshake;
pub mod inventory_content;
pub mod level_chunk;
pub mod move_player;
pub mod network_chunk_publisher_update;
pub mod network_settings;
pub mod play_status;
pub mod player_hotbar;
pub mod raknet;
pub mod resource_pack_stack;
pub mod resource_packs_info;
pub mod set_player_gamemode;
pub mod set_time;
pub mod start_game;
pub mod update_artributes;

View File

@@ -0,0 +1,19 @@
use pumpkin_macros::packet;
use pumpkin_util::math::vector3::Vector3;
use crate::{codec::var_ulong::VarULong, serial::PacketWrite};
#[derive(Debug, PacketWrite)]
#[packet(19)]
pub struct CMovePlayer {
// https://mojang.github.io/bedrock-protocol-docs/html/MovePlayerPacket.html
pub player_runtime_id: VarULong,
pub position: Vector3<f32>,
pub pitch: f32,
pub yaw: f32,
pub y_head_rotation: f32,
pub position_mode: u8,
pub on_ground: bool,
pub riding_runtime_id: VarULong,
pub tick: VarULong,
}

View File

@@ -0,0 +1,43 @@
use std::io::{Error, Write};
use pumpkin_macros::packet;
use pumpkin_util::math::{position::BlockPos, vector2::Vector2};
use crate::{
codec::{var_int::VarInt, var_uint::VarUInt},
serial::PacketWrite,
};
#[packet(121)]
pub struct CNetworkChunkPublisherUpdate {
// https://mojang.github.io/bedrock-protocol-docs/html/NetworkChunkPublisherUpdatePacket.html
pub pos_for_view: BlockPos,
// Is in blocks, not chunks!
pub new_radius: VarUInt,
// TODO
pub server_build_chunk_list: Vec<Vector2<i32>>,
}
impl CNetworkChunkPublisherUpdate {
pub fn new(pos_for_view: BlockPos, new_radius: u32) -> Self {
Self {
pos_for_view,
new_radius: VarUInt(new_radius << 4),
server_build_chunk_list: Vec::new(),
}
}
}
impl PacketWrite for CNetworkChunkPublisherUpdate {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.pos_for_view.write(writer)?;
self.new_radius.write(writer)?;
(self.server_build_chunk_list.len() as u32).write(writer)?;
for chunk in &self.server_build_chunk_list {
VarInt(chunk.x).write(writer)?;
VarInt(chunk.y).write(writer)?;
}
Ok(())
}
}

View File

@@ -1,7 +1,8 @@
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
use crate::serial::PacketWrite;
#[derive(PacketWrite)]
#[packet(143)]
pub struct CNetworkSettings {
compression_threshold: u16,

View File

@@ -1,22 +1,12 @@
use std::io::{Error, Write};
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
#[packet(0x02)]
pub struct CPlayStatus {
status: i32,
}
use crate::serial::PacketWrite;
impl CPlayStatus {
pub fn new(status: PlayStatus) -> Self {
Self {
status: status as i32,
}
}
}
#[repr(i32)]
pub enum PlayStatus {
#[derive(Clone, Copy)]
#[packet(2)]
pub enum CPlayStatus {
LoginSuccess = 0,
OutdatedClient = 1,
OutdatedServer = 2,
@@ -28,3 +18,9 @@ pub enum PlayStatus {
EditorMismatchEditorToVanilla = 8,
EditorMismatchVanillaToEditor = 9,
}
impl PacketWrite for CPlayStatus {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
(*self as i32).write_be(writer)
}
}

View File

@@ -0,0 +1,11 @@
use pumpkin_macros::packet;
use crate::{codec::var_uint::VarUInt, serial::PacketWrite};
#[derive(PacketWrite)]
#[packet(48)]
pub struct CPlayerHotbar {
pub selected_slot: VarUInt,
pub container_id: u8,
pub should_select_block: bool,
}

View File

@@ -1,9 +1,9 @@
use std::net::SocketAddr;
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
use crate::codec::socket_address::SocketAddress;
#[derive(Serialize, Deserialize)]
use crate::serial::PacketWrite;
#[derive(PacketWrite)]
#[packet(0x03)]
pub struct CConnectedPong {
ping_time: u64,
@@ -19,21 +19,21 @@ impl CConnectedPong {
}
}
#[derive(Serialize, Deserialize)]
#[derive(PacketWrite)]
#[packet(0x10)]
pub struct CConnectionRequestAccepted {
client_address: SocketAddress,
client_address: SocketAddr,
system_index: u16,
system_addresses: [SocketAddress; 10],
system_addresses: [SocketAddr; 10],
requested_timestamp: u64,
timestamp: u64,
}
impl CConnectionRequestAccepted {
pub fn new(
client_address: SocketAddress,
client_address: SocketAddr,
system_index: u16,
system_addresses: [SocketAddress; 10],
system_addresses: [SocketAddr; 10],
requested_timestamp: u64,
timestamp: u64,
) -> Self {

View File

@@ -1,9 +1,10 @@
use std::net::SocketAddr;
use pumpkin_macros::packet;
use serde::Serialize;
use crate::{bedrock::RAKNET_MAGIC, codec::socket_address::SocketAddress};
use crate::{bedrock::RAKNET_MAGIC, serial::PacketWrite};
#[derive(Serialize)]
#[derive(PacketWrite)]
#[packet(0x06)]
pub struct COpenConnectionReply1 {
magic: [u8; 16],
@@ -26,18 +27,18 @@ impl COpenConnectionReply1 {
}
}
#[derive(Serialize)]
#[derive(PacketWrite)]
#[packet(0x08)]
pub struct COpenConnectionReply2 {
magic: [u8; 16],
server_guid: u64,
client_address: SocketAddress,
client_address: SocketAddr,
mtu: u16,
security: bool,
}
impl COpenConnectionReply2 {
pub fn new(server_guid: u64, client_address: SocketAddress, mtu: u16, security: bool) -> Self {
pub fn new(server_guid: u64, client_address: SocketAddr, mtu: u16, security: bool) -> Self {
Self {
magic: RAKNET_MAGIC,
server_guid,

View File

@@ -1,21 +1,30 @@
use core::fmt;
use std::io::{Error, Write};
use pumpkin_macros::packet;
use serde::Serialize;
use crate::codec::ascii_string::AsciiString;
use crate::serial::PacketWrite;
#[derive(Serialize)]
#[packet(0x1c)]
pub struct CUnconnectedPong {
time: u64,
server_guid: u64,
magic: [u8; 16],
server_id: AsciiString,
server_id: String,
}
impl PacketWrite for CUnconnectedPong {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.time.write_be(writer)?;
self.server_guid.write_be(writer)?;
writer.write_all(&self.magic)?;
writer.write_all(&(self.server_id.len() as u16).to_be_bytes())?;
writer.write_all(self.server_id.as_bytes())
}
}
pub struct ServerInfo {
/// (MCPE or MCEE for Education Edition)
/// (BE or MCEE for Education Edition)
pub edition: &'static str,
pub motd_line_1: &'static str,
pub protocol_version: u32,
@@ -52,7 +61,7 @@ impl fmt::Display for ServerInfo {
}
impl CUnconnectedPong {
pub fn new(time: u64, server_guid: u64, magic: [u8; 16], server_id: AsciiString) -> Self {
pub fn new(time: u64, server_guid: u64, magic: [u8; 16], server_id: String) -> Self {
Self {
time,
server_guid,

View File

@@ -1,11 +1,13 @@
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
use crate::{bedrock::client::start_game::Experiments, codec::var_uint::VarUInt};
use crate::{
bedrock::client::start_game::Experiments, codec::var_uint::VarUInt, serial::PacketWrite,
};
#[derive(Serialize, Deserialize)]
#[packet(0x07)]
#[derive(PacketWrite)]
#[packet(7)]
pub struct CResourcePackStackPacket {
// https://mojang.github.io/bedrock-protocol-docs/html/ResourcePackStackPacket.html
resource_pack_required: bool,
addons_list_size: VarUInt,
texture_pack_list_size: VarUInt,

View File

@@ -1,8 +1,9 @@
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
#[packet(0x06)]
use crate::serial::PacketWrite;
#[derive(PacketWrite)]
#[packet(6)]
pub struct CResourcePacksInfo {
resource_pack_required: bool,
has_addon_packs: bool,

View File

@@ -0,0 +1,9 @@
use crate::{codec::var_int::VarInt, serial::PacketWrite};
use pumpkin_macros::packet;
#[derive(PacketWrite)]
#[packet(62)]
pub struct CSetPlayerGamemode {
// https://mojang.github.io/bedrock-protocol-docs/html/SetPlayerGameTypePacket.html
pub gamemode: VarInt,
}

View File

@@ -0,0 +1,15 @@
use pumpkin_macros::packet;
use crate::{codec::var_int::VarInt, serial::PacketWrite};
#[derive(PacketWrite)]
#[packet(10)]
pub struct CSetTime {
pub time: VarInt,
}
impl CSetTime {
pub const fn new(time: i32) -> Self {
Self { time: VarInt(time) }
}
}

View File

@@ -1,30 +1,25 @@
use crate::{
bedrock::client::gamerules_changed::GameRules,
codec::{
bedrock_block_pos::BedrockPos, var_int::VarInt, var_long::VarLong, var_uint::VarUInt,
bedrock_block_pos::NetworkPos, var_int::VarInt, var_long::VarLong, var_uint::VarUInt,
var_ulong::VarULong,
},
serial::PacketWrite,
};
use pumpkin_macros::packet;
use pumpkin_util::math::vector3::Vector3;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
pub const GAME_PUBLISH_SETTING_NO_MULTI_PLAY: i32 = 0;
pub const GAME_PUBLISH_SETTING_INVITE_ONLY: i32 = 1;
pub const GAME_PUBLISH_SETTING_FRIENDS_ONLY: i32 = 2;
pub const GAME_PUBLISH_SETTING_FRIENDS_OF_FRIENDS: i32 = 3;
pub const GAME_PUBLISH_SETTING_PUBLIC: i32 = 4;
#[derive(Serialize)]
#[derive(PacketWrite)]
#[packet(11)]
pub struct CStartGame {
// https://mojang.github.io/bedrock-protocol-docs/html/StartGamePacket.html
pub entity_id: VarLong,
pub runtime_entity_id: VarULong,
pub player_gamemode: VarInt,
pub position: Vector3<f32>,
pub yaw: f32,
pub pitch: f32,
pub yaw: f32,
pub level_settings: LevelSettings,
pub level_id: String,
@@ -38,7 +33,7 @@ pub struct CStartGame {
pub current_level_time: u64,
pub enchantment_seed: VarInt,
pub block_properties_size: VarUInt,
//pub block_properties: [GG; 2],
pub multiplayer_correlation_id: String,
pub enable_itemstack_net_manager: bool,
pub server_version: String,
@@ -56,9 +51,9 @@ pub struct CStartGame {
pub server_auth_sounds: bool,
}
#[derive(Serialize)]
// https://mojang.github.io/bedrock-protocol-docs/html/LevelSettings.html
#[derive(PacketWrite)]
pub struct LevelSettings {
// https://mojang.github.io/bedrock-protocol-docs/html/LevelSettings.html
pub seed: u64,
// Spawn Settings
@@ -72,7 +67,7 @@ pub struct LevelSettings {
pub world_gamemode: VarInt,
pub hardcore: bool,
pub difficulty: VarInt,
pub spawn_position: BedrockPos,
pub spawn_position: NetworkPos,
pub has_achievements_disabled: bool,
pub editor_world_type: VarInt,
pub is_created_in_editor: bool,
@@ -97,7 +92,7 @@ pub struct LevelSettings {
pub bonus_chest: bool,
pub has_start_with_map_enabled: bool,
pub permission_level: VarInt,
pub server_chunk_tick_range: i32,
pub server_simulation_distance: i32,
pub has_locked_behavior_pack: bool,
pub has_locked_resource_pack: bool,
pub is_from_locked_world_template: bool,
@@ -113,7 +108,7 @@ pub struct LevelSettings {
// TODO: LE
pub limited_world_width: i32,
pub limited_world_height: i32,
pub is_nether_type: bool,
pub new_nether: bool,
pub edu_shared_uri_button_name: String,
pub edu_shared_uri_link_uri: String,
pub override_force_experimental_gameplay_has_value: bool,
@@ -125,9 +120,26 @@ pub struct LevelSettings {
pub owner_id: String,
}
#[derive(Serialize, Deserialize, Default)]
#[derive(Default, PacketWrite)]
pub struct Experiments {
pub names_size: u32,
//TODO! https://mojang.github.io/bedrock-protocol-docs/html/Experiments.html
pub names_size: u32,
pub experiments_ever_toggled: bool,
}
#[repr(i32)]
pub enum GamePublishSetting {
NoMultiPlay = 0,
InviteOnly = 1,
FriendsOnly = 2,
FriendsOfFriends = 3,
Public = 4,
}
#[derive(PacketWrite)]
pub struct GG {
pub name: String,
pub id: i8,
pub len: VarUInt,
pub end: i8,
}

View File

@@ -0,0 +1,26 @@
use pumpkin_macros::packet;
use crate::{
codec::{var_uint::VarUInt, var_ulong::VarULong},
serial::PacketWrite,
};
#[derive(PacketWrite)]
#[packet(29)]
pub struct CUpdateAttributes {
pub runtime_id: VarULong,
pub attributes: Vec<Attribute>,
pub player_tick: VarULong,
}
#[derive(PacketWrite)]
pub struct Attribute {
pub min_value: f32,
pub max_value: f32,
pub current_value: f32,
pub default_min_value: f32,
pub default_max_value: f32,
pub default_value: f32,
pub name: String,
pub modifiers_list_size: VarUInt,
}

View File

@@ -1,34 +1,27 @@
use std::io::Write;
use bytes::Bytes;
use pumpkin_macros::packet;
use std::io::{Error, Read, Write};
use crate::bedrock::{RAKNET_SPLIT, RakReliability};
use crate::codec::u24::U24;
use crate::ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError};
use crate::{ClientPacket, ServerPacket};
use crate::codec::u24;
use crate::serial::{PacketRead, PacketWrite};
#[packet[0x80]]
pub struct FrameSet {
pub sequence: U24,
pub sequence: u24,
pub frames: Vec<Frame>,
}
impl ServerPacket for FrameSet {
fn read(mut read: impl std::io::Read) -> Result<Self, ReadingError> {
impl FrameSet {
pub fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
Ok(Self {
sequence: read.get_u24()?,
frames: Frame::read(read)?,
sequence: u24::read(reader)?,
frames: Frame::read(reader)?,
})
}
}
impl ClientPacket for FrameSet {
fn write_packet_data(&self, mut write: impl Write) -> Result<(), WritingError> {
write.write_u8(0x84)?;
write.write_u24_be(self.sequence)?;
pub fn write_packet_data<W: Write>(&self, writer: &mut W, id: u8) -> Result<(), Error> {
id.write(writer)?;
self.sequence.write(writer)?;
for frame in &self.frames {
frame.write(&mut write)?;
frame.write(writer)?;
}
Ok(())
}
@@ -37,7 +30,8 @@ impl ClientPacket for FrameSet {
#[derive(Default)]
pub struct Frame {
pub reliability: RakReliability,
pub payload: Bytes,
// If we write a packet we dont want to own the payload to avoid cloning
pub payload: Vec<u8>,
pub reliable_number: u32,
pub sequence_index: u32,
pub order_index: u32,
@@ -48,77 +42,72 @@ pub struct Frame {
}
impl Frame {
pub fn read(mut read: impl std::io::Read) -> Result<Vec<Self>, crate::ser::ReadingError> {
pub fn read<R: Read>(reader: &mut R) -> Result<Vec<Self>, Error> {
let mut frames = Vec::new();
while let Ok(header) = read.get_u8() {
while let Ok(header) = u8::read(reader) {
let mut frame = Self::default();
let reliability_id = (header & 0xE0) >> 5;
let reliability = match RakReliability::from_id(reliability_id) {
Some(reliability) => reliability,
None => {
return Err(ReadingError::Message(format!(
"Invalid RakReliability {reliability_id}"
)));
}
None => return Err(Error::other("Invalid reliability")),
};
let split = (header & RAKNET_SPLIT) != 0;
let length = read.get_u16_be()? >> 3;
let length = u16::read_be(reader)? >> 3;
if reliability.is_reliable() {
frame.reliable_number = read.get_u24()?.0
frame.reliable_number = u24::read(reader)?.0
}
if reliability.is_sequenced() {
frame.sequence_index = read.get_u24()?.0
frame.sequence_index = u24::read(reader)?.0
}
if reliability.is_ordered() {
frame.order_index = read.get_u24()?.0;
frame.order_channel = read.get_u8()?;
frame.order_index = u24::read(reader)?.0;
frame.order_channel = u8::read(reader)?;
}
if split {
frame.split_size = read.get_u32_be()?;
frame.split_id = read.get_u16_be()?;
frame.split_index = read.get_u32_be()?;
frame.split_size = u32::read_be(reader)?;
frame.split_id = u16::read_be(reader)?;
frame.split_index = u32::read_be(reader)?;
}
frame.reliability = reliability;
frame.payload = read.read_boxed_slice(length as usize)?.into();
frame.payload = vec![0; length as usize];
reader.read_exact(&mut frame.payload)?;
frames.push(frame);
}
Ok(frames)
}
pub fn write(&self, mut write: impl Write) -> Result<(), WritingError> {
pub fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let is_split = self.split_size > 0;
let mut flags = self.reliability.to_id() << 5;
if is_split {
flags |= RAKNET_SPLIT;
}
write.write_u8(flags)?;
flags.write(writer)?;
// Size
write.write_u16_be((self.payload.len() << 3) as u16)?;
((self.payload.len() as u16) << 3).write_be(writer)?;
if self.reliability.is_reliable() {
write.write_u24_be(U24(self.reliable_number))?;
u24(self.reliable_number).write(writer)?;
}
if self.reliability.is_sequenced() {
write.write_u24_be(U24(self.sequence_index))?;
u24(self.sequence_index).write(writer)?;
}
if self.reliability.is_ordered() {
write.write_u24_be(U24(self.order_index))?;
write.write_u8(self.order_channel)?;
u24(self.order_index).write(writer)?;
self.order_channel.write(writer)?;
}
if is_split {
write.write_u32_be(self.split_size)?;
write.write_u16_be(self.split_id)?;
write.write_u32_be(self.split_index)?;
self.split_size.write_be(writer)?;
self.split_id.write_be(writer)?;
self.split_index.write_be(writer)?;
}
write.write_slice(&self.payload).unwrap();
Ok(())
writer.write_all(&self.payload)
}
}

View File

@@ -1,6 +1,7 @@
pub mod ack;
pub mod client;
pub mod frame_set;
pub mod network_item;
pub mod packet_decoder;
pub mod packet_encoder;
pub mod server;

View File

@@ -0,0 +1,82 @@
use std::io::{Error, Write};
use crate::{
codec::{var_int::VarInt, var_uint::VarUInt},
serial::PacketWrite,
};
#[derive(Default, Clone)]
pub struct NetworkItemDescriptor {
// I hate mojang
// https://mojang.github.io/bedrock-protocol-docs/html/NetworkItemInstanceDescriptor.html
pub id: VarInt,
pub stack_size: u16,
pub aux_value: VarUInt,
pub block_runtime_id: VarInt,
pub user_data_buffer: ItemInstanceUserData,
}
impl PacketWrite for NetworkItemDescriptor {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.id.write(writer)?;
if self.id.0 != 0 {
self.stack_size.write(writer)?;
self.aux_value.write(writer)?;
self.block_runtime_id.write(writer)?;
self.user_data_buffer.write(writer)?;
}
Ok(())
}
}
#[derive(Default, Clone)]
pub struct ItemInstanceUserData {
// https://mojang.github.io/bedrock-protocol-docs/html/ItemInstanceUserData.html
//compound
place_on_block_size: VarUInt,
destroy_blocks_size: VarUInt,
}
impl PacketWrite for ItemInstanceUserData {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let mut buf = Vec::new();
(-1i16).write(&mut buf)?;
(1i8).write(&mut buf)?;
(10i8).write(&mut buf)?;
VarUInt(0).write(&mut buf)?;
(0i8).write(&mut buf)?;
self.place_on_block_size.write(&mut buf)?;
self.destroy_blocks_size.write(&mut buf)?;
VarUInt(buf.len() as u32).write(writer)?;
writer.write_all(&buf)
}
}
#[derive(Default, Clone)]
pub struct NetworkItemStackDescriptor {
// I hate mojang
// https://mojang.github.io/bedrock-protocol-docs/html/NetworkItemStackDescriptor.html
pub id: VarInt,
pub stack_size: u16,
pub aux_value: VarUInt,
pub net_id: Option<VarInt>,
pub block_runtime_id: VarInt,
pub user_data_buffer: ItemInstanceUserData,
}
impl PacketWrite for NetworkItemStackDescriptor {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.id.write(writer)?;
if self.id.0 != 0 {
self.stack_size.write(writer)?;
self.aux_value.write(writer)?;
self.net_id.write(writer)?;
self.block_runtime_id.write(writer)?;
self.user_data_buffer.write(writer)?;
}
Ok(())
}
}

View File

@@ -1,8 +1,12 @@
use std::io::Cursor;
use std::{
io::Cursor,
pin::Pin,
task::{Context, Poll},
};
use async_compression::tokio::bufread::ZlibDecoder;
use bytes::Bytes;
use tokio::io::{AsyncRead, AsyncReadExt, BufReader};
use tokio::io::{AsyncRead, BufReader, ReadBuf};
use crate::{
Aes128Cfb8Dec, CompressionThreshold, PacketDecodeError, RawPacket, StreamDecryptor,
@@ -19,17 +23,17 @@ pub enum DecompressionReader<R: AsyncRead + Unpin> {
impl<R: AsyncRead + Unpin> AsyncRead for DecompressionReader<R> {
#[inline]
fn poll_read(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> std::task::Poll<std::io::Result<()>> {
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
match self.get_mut() {
Self::Decompress(reader) => {
let reader = std::pin::Pin::new(reader);
let reader = Pin::new(reader);
reader.poll_read(cx, buf)
}
Self::None(reader) => {
let reader = std::pin::Pin::new(reader);
let reader = Pin::new(reader);
reader.poll_read(cx, buf)
}
}
@@ -53,17 +57,17 @@ impl<R: AsyncRead + Unpin> DecryptionReader<R> {
impl<R: AsyncRead + Unpin> AsyncRead for DecryptionReader<R> {
#[inline]
fn poll_read(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> std::task::Poll<std::io::Result<()>> {
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
match self.get_mut() {
Self::Decrypt(reader) => {
let reader = std::pin::Pin::new(reader);
let reader = Pin::new(reader);
reader.poll_read(cx, buf)
}
Self::None(reader) => {
let reader = std::pin::Pin::new(reader);
let reader = Pin::new(reader);
reader.poll_read(cx, buf)
}
}
@@ -103,15 +107,15 @@ impl UDPNetworkDecoder {
pub async fn get_packet_payload(
&mut self,
mut reader: Cursor<Vec<u8>>,
reader: Cursor<Vec<u8>>,
) -> Result<Bytes, PacketDecodeError> {
let mut payload = Vec::new();
reader
.read_to_end(&mut payload)
.await
.map_err(|err| PacketDecodeError::FailedDecompression(err.to_string()))?;
//let mut payload = Vec::new();
//reader
// .read_to_end(&mut payload)
// .await
// .map_err(|err| PacketDecodeError::FailedDecompression(err.to_string()))?;
Ok(payload.into())
Ok(reader.into_inner().into())
}
pub async fn get_game_packet(
@@ -120,7 +124,6 @@ impl UDPNetworkDecoder {
) -> Result<RawPacket, PacketDecodeError> {
if self.compression.is_some() {
let _method = reader.get_u8().unwrap();
dbg!(_method);
// None Compression
}

View File

@@ -1,12 +1,17 @@
use std::{io::Write, net::SocketAddr};
use std::{
io::{self, Error, Write},
net::SocketAddr,
pin::Pin,
task::{Context, Poll},
};
use bytes::Bytes;
use thiserror::Error;
use tokio::{io::AsyncWrite, net::UdpSocket};
use crate::{
Aes128Cfb8Enc, CompressionLevel, CompressionThreshold, PacketEncodeError, StreamEncryptor,
bedrock::SubClient, codec::var_uint::VarUInt, ser::NetworkWriteExt,
Aes128Cfb8Enc, CompressionLevel, CompressionThreshold, StreamEncryptor, bedrock::SubClient,
codec::var_uint::VarUInt, ser::NetworkWriteExt,
};
// raw -> compress -> encrypt
@@ -27,49 +32,43 @@ impl<W: AsyncWrite + Unpin> EncryptionWriter<W> {
impl<W: AsyncWrite + Unpin> AsyncWrite for EncryptionWriter<W> {
fn poll_write(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> std::task::Poll<Result<usize, std::io::Error>> {
) -> Poll<Result<usize, io::Error>> {
match self.get_mut() {
Self::Encrypt(writer) => {
let writer = std::pin::Pin::new(writer);
let writer = Pin::new(writer);
writer.poll_write(cx, buf)
}
Self::None(writer) => {
let writer = std::pin::Pin::new(writer);
let writer = Pin::new(writer);
writer.poll_write(cx, buf)
}
}
}
fn poll_flush(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
match self.get_mut() {
Self::Encrypt(writer) => {
let writer = std::pin::Pin::new(writer);
let writer = Pin::new(writer);
writer.poll_flush(cx)
}
Self::None(writer) => {
let writer = std::pin::Pin::new(writer);
let writer = Pin::new(writer);
writer.poll_flush(cx)
}
}
}
fn poll_shutdown(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
match self.get_mut() {
Self::Encrypt(writer) => {
let writer = std::pin::Pin::new(writer);
let writer = Pin::new(writer);
writer.poll_shutdown(cx)
}
Self::None(writer) => {
let writer = std::pin::Pin::new(writer);
let writer = Pin::new(writer);
writer.poll_shutdown(cx)
}
}
@@ -115,7 +114,7 @@ impl UDPNetworkEncoder {
sub_client_target: SubClient,
packet_payload: Bytes,
mut writer: impl Write,
) -> Result<(), PacketEncodeError> {
) -> Result<(), Error> {
// Game Packet ID
writer.write_u8(0xfe).unwrap();
@@ -159,18 +158,16 @@ impl UDPNetworkEncoder {
.unwrap();
// 5. Write the payload
writer.write_all(&packet_payload).unwrap();
Ok(())
writer.write_all(&packet_payload)
}
pub async fn write_packet(
&mut self,
packet_data: Bytes,
packet_data: &[u8],
addr: SocketAddr,
socket: &UdpSocket,
) -> Result<(), PacketEncodeError> {
socket.send_to(&packet_data, addr).await.unwrap();
Ok(())
) -> Result<(), Error> {
socket.send_to(packet_data, addr).await.map(|_| ())
}
}

View File

@@ -0,0 +1,9 @@
use crate::serial::PacketRead;
use pumpkin_macros::packet;
#[derive(PacketRead)]
#[packet(129)]
pub struct SClientCacheStatus {
// https://mojang.github.io/bedrock-protocol-docs/html/ClientCacheStatusPacket.html
pub cache_supported: bool,
}

View File

@@ -0,0 +1,12 @@
use pumpkin_macros::packet;
use crate::serial::{PacketRead, PacketWrite};
#[derive(Debug, PacketWrite, PacketRead)]
#[packet(47)]
pub struct SContainerClose {
// https://mojang.github.io/bedrock-protocol-docs/html/ContainerClosePacket.html
pub container_id: u8,
pub container_type: u8,
pub server_initiated: bool,
}

View File

@@ -0,0 +1,41 @@
use std::io::{Error, Read};
use pumpkin_macros::packet;
use crate::{codec::var_ulong::VarULong, serial::PacketRead};
#[derive(Debug, PacketRead)]
#[packet(33)]
pub struct SInteraction {
// https://mojang.github.io/bedrock-protocol-docs/html/InteractPacket.html
pub action: Action,
pub target_runtime_id: VarULong,
}
#[derive(Debug)]
#[repr(i8)]
pub enum Action {
Invalid = 0,
StopRiding = 3,
InteractUpdate = 4,
NpcOpen = 5,
OpenInventory = 6,
}
impl PacketRead for Action {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut byte = [0];
reader.read_exact(&mut byte)?;
let this = match byte[0] {
0 => Self::Invalid,
3 => Self::StopRiding,
4 => Self::InteractUpdate,
5 => Self::NpcOpen,
6 => Self::OpenInventory,
_ => return Err(Error::other("")),
};
Ok(this)
}
}

View File

@@ -1,9 +1,35 @@
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
use std::io::{Error, Read};
#[derive(Serialize, Deserialize)]
#[packet(0x01)]
use crate::{codec::var_uint::VarUInt, serial::PacketRead};
#[packet(1)]
pub struct SLogin {
// https://mojang.github.io/bedrock-protocol-docs/html/LoginPacket.html
pub protocol_version: i32,
// TODO: Add More
// https://mojang.github.io/bedrock-protocol-docs/html/connectionRequest.html
pub jwt: Vec<u8>,
pub raw_token: Vec<u8>,
}
impl PacketRead for SLogin {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let protocol_version = i32::read_be(reader)?;
let _len = VarUInt::read(reader)?;
let jwt_len = u32::read(reader)?;
let mut jwt = vec![0; jwt_len as _];
reader.read_exact(&mut jwt)?;
let raw_token_len = u32::read(reader)?;
let mut raw_token = vec![0; raw_token_len as _];
reader.read_exact(&mut raw_token)?;
Ok(Self {
protocol_version,
jwt,
raw_token,
})
}
}

View File

@@ -1,3 +1,10 @@
pub mod client_cache_status;
pub mod container_close;
pub mod interaction;
pub mod login;
pub mod player_auth_input;
pub mod raknet;
pub mod request_chunk_radius;
pub mod request_network_settings;
pub mod resource_pack_response;
pub mod text;

View File

@@ -0,0 +1,110 @@
use pumpkin_macros::packet;
use pumpkin_util::math::{vector2::Vector2, vector3::Vector3};
use crate::{
codec::{var_uint::VarUInt, var_ulong::VarULong},
serial::PacketRead,
};
#[derive(Debug, PacketRead)]
#[packet(144)]
pub struct SPlayerAuthInput {
// https://mojang.github.io/bedrock-protocol-docs/html/PlayerAuthInputPacket.html
pub pitch: f32,
pub yaw: f32,
pub position: Vector3<f32>,
pub move_vec: Vector2<f32>,
pub head_rotation: f32,
pub bit1: u8,
pub bit2: u8,
pub bit3: u8,
pub bit4: u8,
pub bit5: u8,
pub bit6: u8,
pub input_mode: VarUInt,
pub play_mode: VarUInt,
pub new_interaction_model: VarUInt,
pub interact_rotation: Vector2<f32>,
pub client_tick: VarULong,
pub pos_delta: Vector3<f32>,
pub analog_move: Vector2<f32>,
pub camera_orientation: Vector3<f32>,
//pub raw_move_vec: Vector2<f32>,
}
pub enum InputData {
// https://mojang.github.io/bedrock-protocol-docs/html/enums.html#PlayerAuthInputPacket::InputData
Ascend = 0,
Descend = 1,
JumpDown = 3,
SprintDown = 4,
ChangeHeight = 5,
Jumping = 6,
AutoJumpingInWater = 7,
Sneaking = 8,
SneakDown = 9,
Up = 10,
Down = 11,
Left = 12,
Right = 13,
UpLeft = 14,
UpRight = 15,
WantUp = 16,
WantDown = 17,
WantDownSlow = 18,
WantUpSlow = 19,
Sprinting = 20,
AscendBlock = 21,
DescendBlock = 22,
SneakToggleDown = 23,
PersistSneak = 24,
StartSprinting = 25,
StopSprinting = 26,
StartSneaking = 27,
StopSneaking = 28,
StartSwimming = 29,
StopSwimming = 30,
StartJumping = 31,
StartGliding = 32,
StopGliding = 33,
PerformItemInteraction = 34,
PerformBlockActions = 35,
PerformItemStackRequest = 36,
HandledTeleport = 37,
Emoting = 38,
MissedSwing = 39,
StartCrawling = 40,
StopCrawling = 41,
StartFlying = 42,
StopFlying = 43,
ClientAckServerData = 44,
IsInClientPredictedVehicle = 45,
PaddlingLeft = 46,
PaddlingRight = 47,
BlockBreakingDelayEnabled = 48,
HorizontalCollision = 49,
VerticalCollision = 50,
DownLeft = 51,
DownRight = 52,
StartUsingItem = 53,
IsCameraRelativeMovementEnabled = 54,
IsRotControlledByMoveDirection = 55,
StartSpinAttack = 56,
StopSpinAttack = 57,
IsHotbarOnlyTouch = 58,
JumpReleasedRaw = 59,
JumpPressedRaw = 60,
JumpCurrentRaw = 61,
SneakReleasedRaw = 62,
SneakPressedRaw = 63,
SneakCurrentRaw = 64,
InputNum = 65,
}
pub enum InputMode {
Undefined = 0,
Mouse = 1,
Touch = 2,
GamePad = 3,
MotionController = 4,
}

View File

@@ -1,32 +1,37 @@
use std::net::SocketAddr;
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
use crate::codec::socket_address::SocketAddress;
use crate::serial::PacketRead;
#[derive(Serialize, Deserialize)]
#[derive(PacketRead)]
#[packet(0x00)]
pub struct SConnectedPing {
/// Time since start
#[serial(big_endian)]
pub time: u64,
}
#[derive(Serialize, Deserialize)]
#[derive(PacketRead)]
#[packet(0x09)]
pub struct SConnectionRequest {
#[serial(big_endian)]
pub client_guid: u64,
#[serial(big_endian)]
pub time: u64,
pub security: bool,
}
#[derive(Serialize, Deserialize)]
#[derive(PacketRead)]
#[packet(0x13)]
pub struct SNewIncomingConnection {
pub server_address: SocketAddress,
pub internal_address: SocketAddress,
pub server_address: SocketAddr,
pub internal_address: SocketAddr,
#[serial(big_endian)]
pub ping_time: u64,
#[serial(big_endian)]
pub pong_time: u64,
}
#[derive(Serialize, Deserialize)]
#[packet(0x15)]
pub struct SDisconnect;

View File

@@ -1,22 +1,26 @@
use std::net::SocketAddr;
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
use crate::codec::socket_address::SocketAddress;
use crate::serial::PacketRead;
#[derive(Serialize, Deserialize)]
#[derive(PacketRead)]
#[packet(0x05)]
/// The client sends this when attempting to join the server
pub struct SOpenConnectionRequest1 {
pub magic: [u8; 16],
pub protocol_version: u8,
#[serial(big_endian)]
pub mtu: u16,
}
#[derive(Serialize, Deserialize)]
#[derive(PacketRead)]
#[packet(0x07)]
pub struct SOpenConnectionRequest2 {
pub magic: [u8; 16],
pub server_address: SocketAddress,
pub server_address: SocketAddr,
#[serial(big_endian)]
pub mtu: u16,
#[serial(big_endian)]
pub client_guid: u64,
}

View File

@@ -1,11 +1,14 @@
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
use crate::serial::PacketRead;
#[derive(PacketRead)]
#[packet(0x01)]
/// Used to request Server information like MOTD
pub struct SUnconnectedPing {
#[serial(big_endian)]
pub time: u64,
pub magic: [u8; 16],
#[serial(big_endian)]
pub client_guid: u64,
}

View File

@@ -0,0 +1,10 @@
use pumpkin_macros::packet;
use crate::{codec::var_int::VarInt, serial::PacketRead};
#[derive(PacketRead, Debug)]
#[packet(69)]
pub struct SRequestChunkRadius {
pub chunk_radius: VarInt,
pub max_radius: u8,
}

View File

@@ -1,8 +1,10 @@
use pumpkin_macros::packet;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
use crate::serial::PacketRead;
#[derive(PacketRead)]
#[packet(0xC1)]
pub struct SRequestNetworkSettings {
#[serial(big_endian)]
pub protocol_version: i32,
}

View File

@@ -0,0 +1,9 @@
use crate::serial::PacketRead;
use pumpkin_macros::packet;
#[derive(PacketRead)]
#[packet(8)]
pub struct SResourcePackResponse {
pub response: u8,
pub download_size: u16,
}

View File

@@ -0,0 +1,159 @@
use std::io::{Error, Read, Write};
use pumpkin_macros::packet;
use crate::{
codec::var_uint::VarUInt,
serial::{PacketRead, PacketWrite},
};
#[derive(Debug)]
#[packet(9)]
pub struct SText {
// https://mojang.github.io/bedrock-protocol-docs/html/TextPacket.html
pub r#type: TextPacketType,
pub localize: bool,
pub player_name: String,
pub message: String,
pub parameters: Vec<String>,
pub sender_xuid: String,
pub platform_id: String,
pub filtered_message: String,
}
impl SText {
pub fn new(message: String, player_name: String) -> Self {
Self {
r#type: TextPacketType::Chat,
localize: false,
player_name,
message,
parameters: Vec::new(),
sender_xuid: String::new(),
platform_id: String::new(),
filtered_message: String::new(),
}
}
}
impl PacketRead for SText {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let r#type = TextPacketType::read(reader)?;
let localize = bool::read(reader)?;
let mut player_name = String::new();
let message;
let mut parameters = Vec::new();
match r#type {
TextPacketType::Raw
| TextPacketType::Tip
| TextPacketType::SystemMessage
| TextPacketType::TextObjectWhisper
| TextPacketType::TextObject
| TextPacketType::TextObjectAnnouncement => {
message = String::read(reader)?;
}
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => {
player_name = String::read(reader)?;
message = String::read(reader)?;
}
TextPacketType::Translate | TextPacketType::Popup | TextPacketType::JukeboxPopup => {
message = String::read(reader)?;
let count = VarUInt::read(reader)?.0 as usize;
parameters = Vec::with_capacity(count);
for _ in 0..count {
parameters.push(String::read(reader)?);
}
}
}
let sender_xuid = String::read(reader)?;
let platform_id = String::read(reader)?;
let filtered_message = String::read(reader)?;
Ok(Self {
r#type,
localize,
player_name,
message,
parameters,
sender_xuid,
platform_id,
filtered_message,
})
}
}
impl PacketWrite for SText {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.r#type.write(writer)?;
self.localize.write(writer)?;
match self.r#type {
TextPacketType::Raw
| TextPacketType::Tip
| TextPacketType::SystemMessage
| TextPacketType::TextObjectWhisper
| TextPacketType::TextObject
| TextPacketType::TextObjectAnnouncement => {
self.message.write(writer)?;
}
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => {
self.player_name.write(writer)?;
self.message.write(writer)?;
}
TextPacketType::Translate | 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.sender_xuid.write(writer)?;
self.platform_id.write(writer)?;
self.filtered_message.write(writer)
}
}
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum TextPacketType {
Raw = 0,
Chat = 1,
Translate = 2,
Popup = 3,
JukeboxPopup = 4,
Tip = 5,
SystemMessage = 6,
Whisper = 7,
Announcement = 8,
TextObjectWhisper = 9,
TextObject = 10,
TextObjectAnnouncement = 11,
}
impl PacketRead for TextPacketType {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
Ok(match u8::read(reader)? {
0 => Self::Raw,
1 => Self::Chat,
2 => Self::Translate,
3 => Self::Popup,
4 => Self::JukeboxPopup,
5 => Self::Tip,
6 => Self::SystemMessage,
7 => Self::Whisper,
8 => Self::Announcement,
9 => Self::TextObjectWhisper,
10 => Self::TextObject,
11 => Self::TextObjectAnnouncement,
_ => return Err(Error::new(std::io::ErrorKind::InvalidData, "")),
})
}
}
impl PacketWrite for TextPacketType {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
(*self as u8).write(writer)
}
}

View File

@@ -1,21 +0,0 @@
use std::io::Write;
use bytes::BufMut;
use serde::{Serialize, Serializer};
pub struct AsciiString(pub String);
impl Serialize for AsciiString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut buf = Vec::new();
// Prefixed by a short
buf.put_u16(self.0.len() as u16);
buf.write_all(self.0.as_bytes()).unwrap();
serializer.serialize_bytes(&buf)
}
}

View File

@@ -1,22 +1,19 @@
use std::io::{Error, Write};
use pumpkin_util::math::position::BlockPos;
use crate::{
codec::{var_int::VarInt, var_uint::VarUInt},
ser::NetworkWriteExt,
serial::PacketWrite,
};
/// Bedrocks Writes and Reads BlockPos types in Packets differently
pub struct BedrockPos(pub BlockPos);
pub struct NetworkPos(pub BlockPos);
impl serde::Serialize for BedrockPos {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut buf = Vec::new();
buf.write_var_int(&VarInt(self.0.0.x)).unwrap();
buf.write_var_uint(&VarUInt(self.0.0.y as u32)).unwrap();
buf.write_var_int(&VarInt(self.0.0.z)).unwrap();
serializer.serialize_bytes(&buf)
impl PacketWrite for NetworkPos {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
VarInt(self.0.0.x).write(writer)?;
VarUInt(self.0.0.y as u32).write(writer)?;
VarInt(self.0.0.z).write(writer)
}
}

View File

@@ -36,10 +36,7 @@ impl BitSet {
}
impl Serialize for BitSet {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, _serializer: S) -> Result<S::Ok, S::Error> {
todo!()
}
}

View File

@@ -12,10 +12,7 @@ use serde::{
pub struct ItemStackSerializer<'a>(pub Cow<'a, ItemStack>);
impl<'de> Deserialize<'de> for ItemStackSerializer<'static> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = ItemStackSerializer<'static>;
@@ -24,10 +21,7 @@ impl<'de> Deserialize<'de> for ItemStackSerializer<'static> {
formatter.write_str("a valid Slot encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let item_count = seq
.next_element::<VarInt>()?
.ok_or(de::Error::custom("Failed to decode VarInt"))?;
@@ -72,10 +66,7 @@ impl<'de> Deserialize<'de> for ItemStackSerializer<'static> {
}
impl Serialize for ItemStackSerializer<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
if self.0.is_empty() {
VarInt(0).serialize(serializer)
} else {
@@ -150,10 +141,7 @@ impl OptionalItemStackHash {
pub struct OptionalItemStackHash(pub Option<ItemStackHash>);
impl<'de> Deserialize<'de> for OptionalItemStackHash {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = OptionalItemStackHash;
@@ -162,10 +150,7 @@ impl<'de> Deserialize<'de> for OptionalItemStackHash {
formatter.write_str("a valid Slot encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let is_some = seq
.next_element::<bool>()?
.ok_or(de::Error::custom("No is some bool!"))?;
@@ -198,10 +183,7 @@ impl<'de> Deserialize<'de> for OptionalItemStackHash {
}
impl<'de> Deserialize<'de> for ItemComponentHash {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = ItemComponentHash;
@@ -210,10 +192,7 @@ impl<'de> Deserialize<'de> for ItemComponentHash {
formatter.write_str("a valid Slot encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut added = Vec::new();
let mut removed = Vec::new();

View File

@@ -3,10 +3,7 @@ use serde::{Serialize, Serializer};
pub struct Le64(pub i64);
impl Serialize for Le64 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_bytes(&self.0.to_le_bytes())
}
}
@@ -14,10 +11,7 @@ impl Serialize for Le64 {
pub struct Le32(pub i32);
impl Serialize for Le32 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_bytes(&self.0.to_le_bytes())
}
}
@@ -25,10 +19,7 @@ impl Serialize for Le32 {
pub struct Le16(pub i16);
impl Serialize for Le16 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_bytes(&self.0.to_le_bytes())
}
}
@@ -38,10 +29,7 @@ impl Serialize for Le16 {
pub struct LeU64(pub u64);
impl Serialize for LeU64 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_bytes(&self.0.to_le_bytes())
}
}
@@ -49,10 +37,7 @@ impl Serialize for LeU64 {
pub struct LeU32(pub u32);
impl Serialize for LeU32 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_bytes(&self.0.to_le_bytes())
}
}
@@ -60,10 +45,7 @@ impl Serialize for LeU32 {
pub struct LeU16(pub u16);
impl Serialize for LeU16 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_bytes(&self.0.to_le_bytes())
}
}

View File

@@ -1,11 +1,12 @@
pub mod ascii_string;
pub mod bedrock_block_pos;
pub mod bit_set;
pub mod item_stack_seralizer;
pub mod little_endian;
pub mod socket_address;
pub mod u24;
mod u24_type;
pub mod uuid;
pub mod var_int;
pub mod var_long;
pub mod var_uint;
pub mod var_ulong;
pub use u24_type::u24;

View File

@@ -1,92 +0,0 @@
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use bytes::BufMut;
use serde::{
Deserialize, Serialize, Serializer,
de::{self, SeqAccess},
};
#[derive(Clone, Copy)]
pub struct SocketAddress(pub SocketAddr);
impl Serialize for SocketAddress {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let (version, mut buf) = match self.0 {
SocketAddr::V4(_) => (4, Vec::with_capacity(7)),
SocketAddr::V6(_) => (6, Vec::with_capacity(19)),
};
buf.put_u8(version);
match self.0 {
SocketAddr::V4(addr) => buf.extend(addr.ip().octets()),
SocketAddr::V6(addr) => buf.extend(addr.ip().octets()),
};
buf.put_u16(self.0.port());
serializer.serialize_bytes(&buf)
}
}
impl<'de> Deserialize<'de> for SocketAddress {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = SocketAddress;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a valid socket addr")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
if let Some(version) = seq.next_element::<u8>()? {
match version {
4 => {
let ip = seq.next_element::<u32>()?.unwrap();
let port = seq.next_element::<u16>()?.unwrap();
return Ok(SocketAddress(SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::from_bits(ip),
port,
))));
}
6 => {
let _family = seq.next_element::<u16>()?.unwrap();
let port = seq.next_element::<u16>()?.unwrap();
let flowinfo = seq.next_element::<u32>()?.unwrap();
let ip = seq.next_element::<u128>()?.unwrap();
let scope_id = seq.next_element::<u32>()?.unwrap();
return Ok(SocketAddress(SocketAddr::V6(SocketAddrV6::new(
Ipv6Addr::from_bits(ip),
port,
flowinfo,
scope_id,
))));
}
_ => {
return Err(serde::de::Error::custom(format!(
"Wrong Socket Address version {version}"
)));
}
}
}
Err(serde::de::Error::custom("Incomplete Socket Address"))
}
}
deserializer.deserialize_seq(Visitor)
}
}

View File

@@ -1,23 +0,0 @@
use std::io::{Read, Write};
use crate::ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError};
#[derive(Clone, Copy)]
pub struct U24(pub u32);
impl U24 {
pub fn decode(read: &mut impl Read) -> Result<Self, ReadingError> {
let a = read.get_u8()?;
let b = read.get_u8()?;
let c = read.get_u8()?;
Ok(U24(u32::from_le_bytes([a, b, c, 0])))
}
pub fn encode(&self, write: &mut impl Write) -> Result<(), WritingError> {
let data = self.0.to_le_bytes();
write.write_u8(data[0])?;
write.write_u8(data[1])?;
write.write_u8(data[2])?;
Ok(())
}
}

View File

@@ -0,0 +1,22 @@
use std::io::{Error, Read, Write};
use crate::serial::{PacketRead, PacketWrite};
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub struct u24(pub u32);
impl PacketWrite for u24 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let data = self.0.to_le_bytes();
writer.write_all(&data[0..3])
}
}
impl PacketRead for u24 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; 3];
reader.read_exact(&mut buf)?;
Ok(u24(u32::from_le_bytes([buf[0], buf[1], buf[2], 0])))
}
}

View File

@@ -0,0 +1,11 @@
use std::io::{Error, Write};
use uuid::Uuid;
use crate::serial::PacketWrite;
impl PacketWrite for Uuid {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write_all(self.as_bytes())
}
}

View File

@@ -1,5 +1,5 @@
use std::{
io::{ErrorKind, Read, Write},
io::{Error, ErrorKind, Read, Write},
num::NonZeroUsize,
ops::Deref,
};
@@ -11,14 +11,17 @@ use serde::{
};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use crate::ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError};
use crate::{
ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError},
serial::{PacketRead, PacketWrite},
};
pub type VarIntType = i32;
/**
* A variable-length integer type used by the Minecraft network protocol.
*/
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct VarInt(pub VarIntType);
impl VarInt {
@@ -36,10 +39,10 @@ impl VarInt {
pub fn encode(&self, write: &mut impl Write) -> Result<(), WritingError> {
let mut val = self.0;
for _ in 0..Self::MAX_SIZE.get() {
let b: u8 = val as u8 & 0b01111111;
loop {
let b: u8 = val as u8 & 0x7F;
val >>= 7;
write.write_u8(if val == 0 { b } else { b | 0b10000000 })?;
write.write_u8(if val == 0 { b } else { b | 0x80 })?;
if val == 0 {
break;
}
@@ -150,10 +153,7 @@ impl Deref for VarInt {
}
impl Serialize for VarInt {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut value = self.0 as u32;
let mut buf = Vec::new();
@@ -169,10 +169,7 @@ impl Serialize for VarInt {
}
impl<'de> Deserialize<'de> for VarInt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct VarIntVisitor;
impl<'de> Visitor<'de> for VarIntVisitor {
@@ -182,10 +179,7 @@ impl<'de> Deserialize<'de> for VarInt {
formatter.write_str("a valid VarInt encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut val = 0;
for i in 0..VarInt::MAX_SIZE.get() {
if let Some(byte) = seq.next_element::<u8>()? {
@@ -204,3 +198,34 @@ impl<'de> Deserialize<'de> for VarInt {
deserializer.deserialize_seq(VarIntVisitor)
}
}
impl PacketWrite for VarInt {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let mut val = (self.0 << 1) ^ (self.0 >> 31);
loop {
let b: u8 = val as u8 & 0b01111111;
val >>= 7;
if val == 0 {
b.write(writer)?;
break;
} else {
(b | 0b10000000).write(writer)?;
};
}
Ok(())
}
}
impl PacketRead for VarInt {
fn read<W: Read>(read: &mut W) -> Result<Self, Error> {
let mut val = 0;
for i in 0..Self::MAX_SIZE.get() {
let byte = u8::read(read)?;
val |= (i32::from(byte) & 0x7F) << (i * 7);
if byte & 0x80 == 0 {
return Ok(VarInt((val >> 1) ^ (val << 31)));
}
}
Err(Error::new(ErrorKind::InvalidData, ""))
}
}

View File

@@ -1,5 +1,5 @@
use std::{
io::{Read, Write},
io::{Error, Read, Write},
num::NonZeroUsize,
ops::Deref,
};
@@ -12,6 +12,7 @@ use serde::{
use crate::{
WritingError,
ser::{NetworkReadExt, NetworkWriteExt, ReadingError},
serial::PacketWrite,
};
pub type VarLongType = i64;
@@ -37,7 +38,7 @@ impl VarLong {
pub fn encode(&self, write: &mut impl Write) -> Result<(), WritingError> {
let mut x = self.0;
for _ in 0..Self::MAX_SIZE.get() {
loop {
let byte = (x & 0x7F) as u8;
x >>= 7;
if x == 0 {
@@ -109,10 +110,7 @@ impl Deref for VarLong {
}
impl Serialize for VarLong {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut value = self.0 as u64;
let mut buf = Vec::new();
@@ -128,10 +126,7 @@ impl Serialize for VarLong {
}
impl<'de> Deserialize<'de> for VarLong {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct VarLongVisitor;
impl<'de> Visitor<'de> for VarLongVisitor {
@@ -141,10 +136,7 @@ impl<'de> Deserialize<'de> for VarLong {
formatter.write_str("a valid VarInt encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut val = 0;
for i in 0..VarLong::MAX_SIZE.get() {
if let Some(byte) = seq.next_element::<u8>()? {
@@ -163,3 +155,18 @@ impl<'de> Deserialize<'de> for VarLong {
deserializer.deserialize_seq(VarLongVisitor)
}
}
impl PacketWrite for VarLong {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let mut value = (self.0 << 1) ^ (self.0 >> 63);
loop {
let b: u8 = value as u8 & 127;
value >>= 7;
writer.write_all(&if value == 0 { [b] } else { [b | 128] })?;
if value == 0 {
break;
}
}
Ok(())
}
}

View File

@@ -1,5 +1,5 @@
use std::{
io::{ErrorKind, Read, Write},
io::{Error, ErrorKind, Read, Write},
num::NonZeroUsize,
};
@@ -10,7 +10,10 @@ use serde::{
};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use crate::ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError};
use crate::{
ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError},
serial::{PacketRead, PacketWrite},
};
pub type VarUIntType = u32;
@@ -135,10 +138,7 @@ gen_try_from!(isize);
gen_try_from!(usize);
impl Serialize for VarUInt {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut value = self.0;
let mut buf = Vec::with_capacity(5);
@@ -154,10 +154,7 @@ impl Serialize for VarUInt {
}
impl<'de> Deserialize<'de> for VarUInt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct VarIntVisitor;
impl<'de> Visitor<'de> for VarIntVisitor {
@@ -167,10 +164,7 @@ impl<'de> Deserialize<'de> for VarUInt {
formatter.write_str("a valid VarInt encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut val = 0;
for i in 0..VarUInt::MAX_SIZE.get() {
if let Some(byte) = seq.next_element::<u8>()? {
@@ -189,3 +183,35 @@ impl<'de> Deserialize<'de> for VarUInt {
deserializer.deserialize_seq(VarIntVisitor)
}
}
impl PacketWrite for VarUInt {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let mut val = self.0;
loop {
let mut byte = (val & 0x7F) as u8;
val >>= 7;
if val != 0 {
byte |= 0x80;
}
byte.write(writer)?;
if val == 0 {
break;
}
}
Ok(())
}
}
impl PacketRead for VarUInt {
fn read<W: Read>(reader: &mut W) -> Result<Self, Error> {
let mut val = 0;
for i in 0..Self::MAX_SIZE.get() {
let byte = u8::read(reader)?;
val |= (u32::from(byte) & 0x7F) << (i * 7);
if byte & 0x80 == 0 {
return Ok(VarUInt(val));
}
}
Err(Error::new(ErrorKind::InvalidData, ""))
}
}

View File

@@ -1,5 +1,5 @@
use std::{
io::{Read, Write},
io::{Error, Read, Write},
num::NonZeroUsize,
ops::Deref,
};
@@ -12,6 +12,7 @@ use serde::{
use crate::{
WritingError,
ser::{NetworkReadExt, NetworkWriteExt, ReadingError},
serial::{PacketRead, PacketWrite},
};
pub type VarULongType = u64;
@@ -37,7 +38,7 @@ impl VarULong {
pub fn encode(&self, write: &mut impl Write) -> Result<(), WritingError> {
let mut x = self.0;
for _ in 0..Self::MAX_SIZE.get() {
loop {
let byte = (x & 0x7F) as u8;
x >>= 7;
if x == 0 {
@@ -109,10 +110,7 @@ impl Deref for VarULong {
}
impl Serialize for VarULong {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut value = self.0;
let mut buf = Vec::new();
@@ -128,10 +126,7 @@ impl Serialize for VarULong {
}
impl<'de> Deserialize<'de> for VarULong {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct VarLongVisitor;
impl<'de> Visitor<'de> for VarLongVisitor {
@@ -141,10 +136,7 @@ impl<'de> Deserialize<'de> for VarULong {
formatter.write_str("a valid VarInt encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut val = 0;
for i in 0..VarULong::MAX_SIZE.get() {
if let Some(byte) = seq.next_element::<u8>()? {
@@ -163,3 +155,34 @@ impl<'de> Deserialize<'de> for VarULong {
deserializer.deserialize_seq(VarLongVisitor)
}
}
impl PacketWrite for VarULong {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
let mut x = self.0;
loop {
let byte = (x & 0x7F) as u8;
x >>= 7;
if x == 0 {
byte.write(writer)?;
break;
}
(byte | 0x80).write(writer)?;
}
Ok(())
}
}
impl PacketRead for VarULong {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut val = 0;
for i in 0..Self::MAX_SIZE.get() {
let byte = u8::read(reader)?;
val |= (u64::from(byte) & 0b01111111) << (i * 7);
if byte & 0b10000000 == 0 {
return Ok(VarULong(val));
}
}
Err(Error::other("Invalid VarUInt"))
}
}

View File

@@ -3,7 +3,7 @@ use std::io::Write;
use crate::{ClientPacket, WritingError, ser::NetworkWriteExt};
use pumpkin_data::{
block_properties::get_block,
Block,
fluid::Fluid,
packet::clientbound::CONFIG_UPDATE_TAGS,
tag::{RegistryKey, get_registry_key_tags},
@@ -40,7 +40,7 @@ impl ClientPacket for CUpdateTags<'_> {
p.write_string_bounded(key, u16::MAX as usize)?;
p.write_list(values, |p, string_id| {
let id = match registry_key {
RegistryKey::Block => get_block(string_id).unwrap().id as i32,
RegistryKey::Block => Block::from_name(string_id).unwrap().id as i32,
RegistryKey::Fluid => Fluid::ident_to_fluid_id(string_id).unwrap() as i32,
_ => unimplemented!(),
};

View File

@@ -29,10 +29,7 @@ impl CMultiBlockUpdate {
}
impl Serialize for CMultiBlockUpdate {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut tuple = serializer.serialize_tuple(2 + self.positions_to_state_ids.len())?;
tuple.serialize_element(&vector3::packed_chunk_pos(&self.chunk_section))?;

View File

@@ -19,10 +19,7 @@ pub struct SClickSlot {
}
impl<'de> Deserialize<'de> for SClickSlot {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = SClickSlot;
@@ -31,10 +28,7 @@ impl<'de> Deserialize<'de> for SClickSlot {
formatter.write_str("a valid VarInt encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let sync_id = seq
.next_element::<VarInt>()?
.ok_or(de::Error::custom("Failed to decode u8"))?;

View File

@@ -1,6 +1,8 @@
use std::{
io::{Read, Write},
io::{Error, Read, Write},
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, BlockSizeUser, generic_array::GenericArray};
@@ -12,11 +14,11 @@ use pumpkin_util::{
};
use ser::{ReadingError, WritingError};
use serde::{
Deserialize, Serialize, Serializer,
de::{DeserializeSeed, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
de::{DeserializeSeed, SeqAccess, Visitor},
};
use thiserror::Error;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use crate::packet::Packet;
@@ -27,6 +29,7 @@ pub mod packet;
#[cfg(feature = "query")]
pub mod query;
pub mod ser;
pub mod serial;
pub const MAX_PACKET_SIZE: u64 = 2097152;
pub const MAX_PACKET_DATA_SIZE: usize = 8388608;
@@ -72,36 +75,27 @@ impl TryFrom<VarInt> for ConnectionState {
}
struct IdOrVisitor<T>(PhantomData<T>);
impl<'de, T> Visitor<'de> for IdOrVisitor<T>
where
T: Deserialize<'de>,
{
impl<'de, T: Deserialize<'de>> Visitor<'de> for IdOrVisitor<T> {
type Value = IdOr<T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("A VarInt followed by a value if the VarInt is 0")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
enum IdOrStateDeserializer<T> {
Init,
Id(u16),
Value(T),
}
impl<'de, T> DeserializeSeed<'de> for &mut IdOrStateDeserializer<T>
where
T: Deserialize<'de>,
{
impl<'de, T: Deserialize<'de>> DeserializeSeed<'de> for &mut IdOrStateDeserializer<T> {
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: Deserializer<'de>>(
self,
deserializer: D,
) -> Result<Self::Value, D::Error> {
match self {
IdOrStateDeserializer::Init => {
// Get the VarInt
@@ -154,23 +148,14 @@ pub enum IdOr<T> {
Value(T),
}
impl<'de, T> Deserialize<'de> for IdOr<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
impl<'de, T: Deserialize<'de>> Deserialize<'de> for IdOr<T> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_seq(IdOrVisitor(PhantomData))
}
}
impl<T: Serialize> Serialize for IdOr<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
IdOr::Id(id) => VarInt::from(*id + 1).serialize(serializer),
IdOr::Value(value) => {
@@ -213,12 +198,12 @@ impl<R: AsyncRead + Unpin> StreamDecryptor<R> {
impl<R: AsyncRead + Unpin> AsyncRead for StreamDecryptor<R> {
fn poll_read(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> std::task::Poll<std::io::Result<()>> {
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
let ref_self = self.get_mut();
let read = std::pin::Pin::new(&mut ref_self.read);
let read = Pin::new(&mut ref_self.read);
let cipher = &mut ref_self.cipher;
// Get the starting position
@@ -226,7 +211,7 @@ impl<R: AsyncRead + Unpin> AsyncRead for StreamDecryptor<R> {
// Read the raw data
let internal_poll = read.poll_read(cx, buf);
if matches!(internal_poll, std::task::Poll::Ready(Ok(_))) {
if matches!(internal_poll, Poll::Ready(Ok(_))) {
// Decrypt the raw data in-place, note that our block size is 1 byte, so this is always safe
for block in buf.filled_mut()[original_fill..].chunks_mut(Aes128Cfb8Dec::block_size()) {
cipher.decrypt_block_mut(block.into());
@@ -259,10 +244,10 @@ impl<W: AsyncWrite + Unpin> StreamEncryptor<W> {
impl<W: AsyncWrite + Unpin> AsyncWrite for StreamEncryptor<W> {
fn poll_write(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> std::task::Poll<Result<usize, std::io::Error>> {
) -> Poll<Result<usize, Error>> {
let ref_self = self.get_mut();
let cipher = &mut ref_self.cipher;
@@ -283,46 +268,40 @@ impl<W: AsyncWrite + Unpin> AsyncWrite for StreamEncryptor<W> {
cipher.encrypt_block_b2b_mut(block.into(), out_block);
}
let write = std::pin::Pin::new(&mut ref_self.write);
let write = Pin::new(&mut ref_self.write);
match write.poll_write(cx, &out) {
std::task::Poll::Pending => {
Poll::Pending => {
ref_self.last_unwritten_encrypted_byte = Some(out[0]);
if total_written == 0 {
//If we didn't write anything, return pending
return std::task::Poll::Pending;
return Poll::Pending;
} else {
// Otherwise, we actually did write something
return std::task::Poll::Ready(Ok(total_written));
return Poll::Ready(Ok(total_written));
}
}
std::task::Poll::Ready(result) => {
Poll::Ready(result) => {
ref_self.last_unwritten_encrypted_byte = None;
match result {
Ok(written) => total_written += written,
Err(err) => return std::task::Poll::Ready(Err(err)),
Err(err) => return Poll::Ready(Err(err)),
}
}
}
}
std::task::Poll::Ready(Ok(total_written))
Poll::Ready(Ok(total_written))
}
fn poll_flush(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
let ref_self = self.get_mut();
let write = std::pin::Pin::new(&mut ref_self.write);
let write = Pin::new(&mut ref_self.write);
write.poll_flush(cx)
}
fn poll_shutdown(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
let ref_self = self.get_mut();
let write = std::pin::Pin::new(&mut ref_self.write);
let write = Pin::new(&mut ref_self.write);
write.poll_shutdown(cx)
}
}
@@ -340,6 +319,14 @@ pub trait ServerPacket: Packet + Sized {
fn read(read: impl Read) -> Result<Self, ReadingError>;
}
pub trait BClientPacket: Packet {
fn write_packet(&self, writer: impl Write) -> Result<(), Error>;
}
pub trait BServerPacket: Packet + Sized {
fn read(read: impl Read) -> Result<Self, Error>;
}
/// Errors that can occur during packet encoding.
#[derive(Error, Debug)]
pub enum PacketEncodeError {
@@ -482,10 +469,7 @@ pub enum Label {
}
impl Serialize for Label {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Label::BuiltIn(link_type) => link_type.serialize(serializer),
Label::TextComponent(component) => component.serialize(serializer),
@@ -513,36 +497,24 @@ impl<'a> Link<'a> {
}
}
#[derive(Clone, Copy)]
#[repr(i32)]
pub enum LinkType {
BugReport,
CommunityGuidelines,
Support,
Status,
Feedback,
Community,
Website,
Forums,
News,
Announcements,
BugReport = 0,
CommunityGuidelines = 1,
Support = 2,
Status = 3,
Feedback = 4,
Community = 5,
Website = 6,
Forums = 7,
News = 8,
Announcements = 9,
}
impl Serialize for LinkType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
LinkType::BugReport => VarInt(0).serialize(serializer),
LinkType::CommunityGuidelines => VarInt(1).serialize(serializer),
LinkType::Support => VarInt(2).serialize(serializer),
LinkType::Status => VarInt(3).serialize(serializer),
LinkType::Feedback => VarInt(4).serialize(serializer),
LinkType::Community => VarInt(5).serialize(serializer),
LinkType::Website => VarInt(6).serialize(serializer),
LinkType::Forums => VarInt(7).serialize(serializer),
LinkType::News => VarInt(8).serialize(serializer),
LinkType::Announcements => VarInt(9).serialize(serializer),
}
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
VarInt(*self as i32).serialize(serializer)
}
}

View File

@@ -1,33 +1,40 @@
use std::io::{Read, Write};
use std::io::{Error, Read, Write};
use serde::{Serialize, de::DeserializeOwned};
use crate::{
ClientPacket, ReadingError, ServerPacket, WritingError,
BClientPacket, BServerPacket, ClientPacket, ReadingError, ServerPacket, WritingError,
codec::var_int::VarIntType,
ser::{deserializer, serializer},
serial::{PacketRead, PacketWrite},
};
pub trait Packet {
const PACKET_ID: VarIntType;
}
impl<P> ClientPacket for P
where
P: Packet + Serialize,
{
impl<P: Packet + Serialize> ClientPacket for P {
fn write_packet_data(&self, write: impl Write) -> Result<(), WritingError> {
let mut serializer = serializer::Serializer::new(write);
self.serialize(&mut serializer)
}
}
impl<P> ServerPacket for P
where
P: Packet + DeserializeOwned,
{
impl<P: Packet + DeserializeOwned> ServerPacket for P {
fn read(read: impl Read) -> Result<P, ReadingError> {
let mut deserializer = deserializer::Deserializer::new(read);
P::deserialize(&mut deserializer)
}
}
impl<P: Packet + PacketWrite> BClientPacket for P {
fn write_packet(&self, mut writer: impl Write) -> Result<(), Error> {
self.write(&mut writer)
}
}
impl<P: Packet + PacketRead> BServerPacket for P {
fn read(mut read: impl Read) -> Result<Self, Error> {
P::read(&mut read)
}
}

View File

@@ -1,7 +1,7 @@
use std::fmt::Display;
use crate::ser::NetworkReadExt;
use serde::de::IntoDeserializer;
use serde::de::{EnumAccess, IntoDeserializer, VariantAccess, Visitor};
use super::{Read, ReadingError};
use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess};
@@ -25,110 +25,65 @@ impl<R: Read> Deserializer<R> {
impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
type Error = ReadingError;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_any<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Self::Error> {
unimplemented!(
"This is impossible to do, since you cannot infer the data structure from the packet"
)
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_bool(self.inner.get_bool()?)
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_i8(self.inner.get_i8()?)
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_i16(self.inner.get_i16_be()?)
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_i32(self.inner.get_i32_be()?)
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_i64(self.inner.get_i64_be()?)
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_u8(self.inner.get_u8()?)
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_u16(self.inner.get_u16_be()?)
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_u32(self.inner.get_u32_be()?)
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_u64(self.inner.get_u64_be()?)
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_f32(self.inner.get_f32_be()?)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_f64(self.inner.get_f64_be()?)
}
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_i128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_i128(self.inner.get_i128_be()?)
}
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_u128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_u128(self.inner.get_u128_be()?)
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
let u32_val = self.inner.get_u32_be()?;
match char::from_u32(u32_val) {
Some(c) => visitor.visit_char(c),
@@ -138,38 +93,23 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
}
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
self.deserialize_string(visitor)
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_str(&self.inner.get_string()?)
}
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_bytes<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Self::Error> {
unimplemented!()
}
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_byte_buf<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Self::Error> {
unimplemented!()
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
if self.inner.get_bool()? {
visitor.visit_some(self)
} else {
@@ -177,39 +117,27 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
}
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_unit()
}
fn deserialize_unit_struct<V>(
fn deserialize_unit_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
) -> Result<V::Value, Self::Error> {
visitor.visit_unit()
}
fn deserialize_newtype_struct<V>(
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
) -> Result<V::Value, Self::Error> {
unimplemented!()
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
struct Access<'a, R: Read> {
deserializer: &'a mut Deserializer<R>,
}
@@ -217,10 +145,10 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
impl<'de, R: Read> SeqAccess<'de> for Access<'_, R> {
type Error = ReadingError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
fn next_element_seed<T: DeserializeSeed<'de>>(
&mut self,
seed: T,
) -> Result<Option<T::Value>, Self::Error> {
let value = DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
Ok(Some(value))
}
@@ -229,10 +157,11 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
visitor.visit_seq(Access { deserializer: self })
}
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_tuple<V: Visitor<'de>>(
self,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error> {
struct Access<'a, R: Read> {
deserializer: &'a mut Deserializer<R>,
len: usize,
@@ -241,10 +170,10 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
impl<'de, R: Read> SeqAccess<'de> for Access<'_, R> {
type Error = ReadingError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
fn next_element_seed<T: DeserializeSeed<'de>>(
&mut self,
seed: T,
) -> Result<Option<T::Value>, Self::Error> {
if self.len > 0 {
self.len -= 1;
let value = DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
@@ -261,22 +190,16 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
})
}
fn deserialize_tuple_struct<V>(
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
) -> Result<V::Value, Self::Error> {
self.deserialize_tuple(len, visitor)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
let len = self.inner.get_var_int()?.0 as usize;
struct Access<'a, R: Read> {
deserializer: &'a mut Deserializer<R>,
@@ -286,20 +209,20 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
impl<'de, R: Read> MapAccess<'de> for Access<'_, R> {
type Error = ReadingError;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: DeserializeSeed<'de>,
{
fn next_key_seed<K: DeserializeSeed<'de>>(
&mut self,
seed: K,
) -> Result<Option<K::Value>, Self::Error> {
if self.len == 0 {
return Ok(None);
}
seed.deserialize(&mut *self.deserializer).map(Some)
}
fn next_value_seed<Val>(&mut self, seed: Val) -> Result<Val::Value, Self::Error>
where
Val: DeserializeSeed<'de>,
{
fn next_value_seed<Val: DeserializeSeed<'de>>(
&mut self,
seed: Val,
) -> Result<Val::Value, Self::Error> {
self.len -= 1;
seed.deserialize(&mut *self.deserializer)
}
@@ -311,53 +234,44 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
})
}
fn deserialize_struct<V>(
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
) -> Result<V::Value, Self::Error> {
self.deserialize_tuple(fields.len(), visitor)
}
fn deserialize_enum<V>(
fn deserialize_enum<V: Visitor<'de>>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
) -> Result<V::Value, Self::Error> {
visitor.visit_enum(self)
}
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_identifier<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Self::Error> {
unimplemented!()
}
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn deserialize_ignored_any<V: Visitor<'de>>(
self,
_visitor: V,
) -> Result<V::Value, Self::Error> {
unimplemented!()
}
}
impl<'de, R: Read> de::EnumAccess<'de> for &mut Deserializer<R> {
impl<'de, R: Read> EnumAccess<'de> for &mut Deserializer<R> {
type Error = ReadingError;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: de::DeserializeSeed<'de>,
{
fn variant_seed<V: DeserializeSeed<'de>>(
self,
seed: V,
) -> Result<(V::Value, Self::Variant), Self::Error> {
let variant_index_i32 = self.inner.get_var_int()?.0;
let variant_index_u32: u32 = variant_index_i32.try_into().map_err(|_| {
ReadingError::Message(format!(
@@ -369,35 +283,33 @@ impl<'de, R: Read> de::EnumAccess<'de> for &mut Deserializer<R> {
}
}
impl<'de, R: Read> de::VariantAccess<'de> for &mut Deserializer<R> {
impl<'de, R: Read> VariantAccess<'de> for &mut Deserializer<R> {
type Error = ReadingError;
fn unit_variant(self) -> Result<(), Self::Error> {
Ok(())
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
fn newtype_variant_seed<T: DeserializeSeed<'de>>(
self,
seed: T,
) -> Result<T::Value, Self::Error> {
seed.deserialize(self)
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
fn tuple_variant<V: Visitor<'de>>(
self,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error> {
de::Deserializer::deserialize_tuple(self, len, visitor)
}
fn struct_variant<V>(
fn struct_variant<V: Visitor<'de>>(
self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
) -> Result<V::Value, Self::Error> {
de::Deserializer::deserialize_struct(self, "", fields, visitor)
}
}

View File

@@ -3,7 +3,9 @@ use std::io::{Read, Write};
use crate::{
FixedBitSet,
codec::{bit_set::BitSet, u24::U24, var_int::VarInt, var_long::VarLong, var_uint::VarUInt},
codec::{
bit_set::BitSet, var_int::VarInt, var_long::VarLong, var_uint::VarUInt, var_ulong::VarULong,
},
};
pub mod deserializer;
@@ -15,11 +17,10 @@ pub mod serializer;
// TODO: This is a bit hacky
const NO_PREFIX_MARKER: &str = "__network_no_prefix";
pub fn network_serialize_no_prefix<T, S>(input: T, serializer: S) -> Result<S::Ok, S::Error>
where
T: serde::Serialize,
S: serde::Serializer,
{
pub fn network_serialize_no_prefix<T: serde::Serialize, S: serde::Serializer>(
input: T,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_newtype_struct(NO_PREFIX_MARKER, &input)
}
@@ -64,10 +65,10 @@ pub trait NetworkReadExt {
fn read_remaining_to_boxed_slice(&mut self, bound: usize) -> Result<Box<[u8]>, ReadingError>;
fn get_bool(&mut self) -> Result<bool, ReadingError>;
fn get_u24(&mut self) -> Result<U24, ReadingError>;
fn get_var_int(&mut self) -> Result<VarInt, ReadingError>;
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_resource_location(&mut self) -> Result<ResourceLocation, ReadingError>;
@@ -114,10 +115,6 @@ impl<R: Read> NetworkReadExt for R {
Ok(buf[0])
}
fn get_u24(&mut self) -> Result<U24, ReadingError> {
U24::decode(self)
}
get_number_be!(get_i16_be, i16);
get_number_be!(get_u16_be, u16);
get_number_be!(get_i32_be, i32);
@@ -178,6 +175,10 @@ impl<R: Read> NetworkReadExt for R {
VarLong::decode(self)
}
fn get_var_ulong(&mut self) -> Result<VarULong, ReadingError> {
VarULong::decode(self)
}
fn get_string_bounded(&mut self, bound: usize) -> Result<String, ReadingError> {
let size = self.get_var_uint()?.0 as usize;
if size > bound {
@@ -244,7 +245,6 @@ pub trait NetworkWriteExt {
fn write_u8(&mut self, data: u8) -> Result<(), WritingError>;
fn write_i16_be(&mut self, data: i16) -> Result<(), WritingError>;
fn write_u16_be(&mut self, data: u16) -> Result<(), WritingError>;
fn write_u24_be(&mut self, data: U24) -> Result<(), WritingError>;
fn write_i32_be(&mut self, data: i32) -> Result<(), WritingError>;
fn write_u32_be(&mut self, data: u32) -> Result<(), WritingError>;
fn write_i64_be(&mut self, data: i64) -> Result<(), WritingError>;
@@ -327,10 +327,6 @@ impl<W: Write> NetworkWriteExt for W {
.map_err(WritingError::IoError)
}
fn write_u24_be(&mut self, data: U24) -> Result<(), WritingError> {
data.encode(self)
}
write_number_be!(write_i16_be, i16);
write_number_be!(write_u16_be, u16);
write_number_be!(write_i32_be, i32);

View File

@@ -44,10 +44,7 @@ impl<W: Write> ser::SerializeSeq for NonPrefixedSeqSerializer<'_, W> {
type Ok = ();
type Error = WritingError;
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut *self.wrapped).map(|_| ())
}
@@ -89,29 +86,23 @@ impl<W: Write> ser::Serializer for NonPrefixedSeqSerializer<'_, W> {
))
}
fn serialize_newtype_struct<T>(
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
name: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
) -> Result<Self::Ok, Self::Error> {
Err(WritingError::Serde(format!(
"Expected a sequence but found a newtype struct {name}!"
)))
}
fn serialize_newtype_variant<T>(
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
) -> Result<Self::Ok, Self::Error> {
Err(WritingError::Serde(format!(
"Expected a sequence but found a newtype variant {name}!"
)))
@@ -125,10 +116,7 @@ impl<W: Write> ser::Serializer for NonPrefixedSeqSerializer<'_, W> {
Ok(self)
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
self.wrapped.serialize_bool(true)?;
value.serialize(self)
}
@@ -270,14 +258,11 @@ impl<W: Write> ser::Serializer for &mut Serializer<W> {
Ok(self)
}
fn serialize_newtype_struct<T>(
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
) -> Result<Self::Ok, Self::Error> {
// TODO: This is super sketchy... is there a way to do it better? Can we choose what
// serializer to use on a struct somehow from within the struct?
if name == "TextComponent" {
@@ -292,16 +277,13 @@ impl<W: Write> ser::Serializer for &mut Serializer<W> {
value.serialize(self)
}
}
fn serialize_newtype_variant<T>(
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_name: &'static str,
variant_index: u32,
_variant: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
) -> Result<Self::Ok, Self::Error> {
self.write
.write_var_int(&variant_index.try_into().map_err(|_| {
WritingError::Message(format!("{variant_index} isn't representable as a VarInt"))
@@ -324,10 +306,7 @@ impl<W: Write> ser::Serializer for &mut Serializer<W> {
Ok(self)
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
self.write.write_bool(true)?;
value.serialize(self)
}
@@ -426,10 +405,7 @@ impl<W: Write> ser::SerializeSeq for &mut Serializer<W> {
type Error = WritingError;
// Serialize a single element of the sequence.
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
@@ -443,10 +419,7 @@ impl<W: Write> ser::SerializeTuple for &mut Serializer<W> {
type Ok = ();
type Error = WritingError;
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
@@ -460,10 +433,7 @@ impl<W: Write> ser::SerializeTupleStruct for &mut Serializer<W> {
type Ok = ();
type Error = WritingError;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
@@ -485,10 +455,7 @@ impl<W: Write> ser::SerializeTupleVariant for &mut Serializer<W> {
type Ok = ();
type Error = WritingError;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
@@ -509,17 +476,11 @@ impl<W: Write> ser::SerializeMap for &mut Serializer<W> {
type Ok = ();
type Error = WritingError;
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Self::Error> {
key.serialize(&mut **self)
}
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
@@ -534,10 +495,11 @@ impl<W: Write> ser::SerializeStruct for &mut Serializer<W> {
type Ok = ();
type Error = WritingError;
fn serialize_field<T>(&mut self, _key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
_key: &'static str,
value: &T,
) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}
@@ -557,10 +519,11 @@ impl<W: Write> ser::SerializeStructVariant for &mut Serializer<W> {
type Ok = ();
type Error = WritingError;
fn serialize_field<T>(&mut self, _key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
_key: &'static str,
value: &T,
) -> Result<(), Self::Error> {
value.serialize(&mut **self)
}

View File

@@ -0,0 +1,197 @@
use std::{
io::{Error, Read},
net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
};
use pumpkin_util::math::{vector2::Vector2, vector3::Vector3};
use crate::{codec::var_uint::VarUInt, serial::PacketRead};
impl PacketRead for bool {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0];
reader.read_exact(&mut buf)?;
Ok(buf[0] != 0)
}
}
impl PacketRead for i8 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0];
reader.read_exact(&mut buf)?;
Ok(buf[0] as Self)
}
}
impl PacketRead for i16 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_le_bytes(buf))
}
}
impl PacketRead for i32 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_le_bytes(buf))
}
fn read_be<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_be_bytes(buf))
}
}
impl PacketRead for i64 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_le_bytes(buf))
}
}
impl PacketRead for u8 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0];
reader.read_exact(&mut buf)?;
Ok(buf[0])
}
}
impl PacketRead for u16 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_le_bytes(buf))
}
fn read_be<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_be_bytes(buf))
}
}
impl PacketRead for u32 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_le_bytes(buf))
}
fn read_be<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_be_bytes(buf))
}
}
impl PacketRead for u64 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_le_bytes(buf))
}
fn read_be<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_be_bytes(buf))
}
}
impl PacketRead for f32 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_le_bytes(buf))
}
}
impl PacketRead for f64 {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let mut buf = [0; size_of::<Self>()];
reader.read_exact(&mut buf)?;
Ok(Self::from_le_bytes(buf))
}
}
impl<T: PacketRead, const N: usize> PacketRead for [T; N] {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
#[allow(clippy::uninit_assumed_init)]
let mut buf: [T; N] = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
for i in &mut buf {
*i = T::read(reader)?;
}
Ok(buf)
}
}
impl PacketRead for String {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let vec = Vec::read(reader)?;
Ok(unsafe { String::from_utf8_unchecked(vec) })
}
}
impl PacketRead for Vec<u8> {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
#[allow(clippy::uninit_vec)]
{
let len = VarUInt::read(reader)?.0 as _;
let mut buf = Vec::with_capacity(len);
unsafe {
buf.set_len(len);
}
reader.read_exact(&mut buf)?;
Ok(buf)
}
}
}
impl<T: PacketRead> PacketRead for Vector3<T> {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
Ok(Self {
x: T::read(reader)?,
y: T::read(reader)?,
z: T::read(reader)?,
})
}
}
impl<T: PacketRead> PacketRead for Vector2<T> {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
Ok(Self {
x: T::read(reader)?,
y: T::read(reader)?,
})
}
}
impl PacketRead for SocketAddr {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
match u8::read(reader)? {
4 => {
let mut ip = [0; 4];
reader.read_exact(&mut ip)?;
let port = u16::read_be(reader)?;
Ok(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(ip), port)))
}
6 => {
let mut ip = [0; 16];
reader.read_exact(&mut ip)?;
let port = u16::read_be(reader)?;
Ok(SocketAddr::V6(SocketAddrV6::new(
Ipv6Addr::from(ip),
port,
0, // flowinfo
0, // scope_id
)))
}
_ => Err(Error::other("Invalid socket address version")),
}
}
}

View File

@@ -0,0 +1,18 @@
pub mod deserializer;
pub mod serializer;
pub use pumpkin_macros::{PacketRead, PacketWrite};
use std::io::{Error, Read, Write};
pub trait PacketWrite {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error>;
fn write_be<W: Write>(&self, _writer: &mut W) -> Result<(), Error> {
panic!("not implemented")
}
}
pub trait PacketRead: Sized {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error>;
fn read_be<R: Read>(_reader: &mut R) -> Result<Self, Error> {
panic!("not implemented")
}
}

View File

@@ -0,0 +1,167 @@
use std::{
io::{Error, Write},
net::SocketAddr,
};
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
use crate::{
codec::{var_int::VarInt, var_uint::VarUInt},
serial::PacketWrite,
};
impl PacketWrite for bool {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&if *self { [1] } else { [0] }).map(|_| ())
}
}
impl PacketWrite for i8 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
}
impl PacketWrite for i16 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
}
impl PacketWrite for i32 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
fn write_be<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_be_bytes()).map(|_| ())
}
}
impl PacketWrite for i64 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
fn write_be<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_be_bytes()).map(|_| ())
}
}
impl PacketWrite for u8 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
}
impl PacketWrite for u16 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
fn write_be<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_be_bytes()).map(|_| ())
}
}
impl PacketWrite for u32 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
fn write_be<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_be_bytes()).map(|_| ())
}
}
impl PacketWrite for u64 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
fn write_be<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_be_bytes()).map(|_| ())
}
}
impl PacketWrite for f32 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
}
impl PacketWrite for f64 {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(&self.to_le_bytes()).map(|_| ())
}
}
impl<T: PacketWrite, const N: usize> PacketWrite for [T; N] {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
for item in self.iter() {
item.write(writer)?;
}
Ok(())
}
}
impl<T: PacketWrite> PacketWrite for Vec<T> {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
for item in self.iter() {
item.write(writer)?;
}
Ok(())
}
}
impl PacketWrite for String {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
VarUInt(self.len() as _).write(writer)?;
writer.write_all(self.as_bytes())
}
}
impl<T: PacketWrite> PacketWrite for Vector3<T> {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.x.write(writer)?;
self.y.write(writer)?;
self.z.write(writer)
}
}
impl PacketWrite for BlockPos {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
VarInt(self.0.x).write(writer)?;
VarInt(self.0.y).write(writer)?;
VarInt(self.0.z).write(writer)
}
}
impl<T: PacketWrite> PacketWrite for Option<T> {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
match self {
Self::Some(value) => {
true.write(writer)?;
value.write(writer)
}
Self::None => false.write(writer),
}
}
}
impl PacketWrite for SocketAddr {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
match self {
SocketAddr::V4(addr) => {
writer.write_all(&[4])?;
writer.write_all(&addr.ip().octets())?;
}
SocketAddr::V6(addr) => {
writer.write_all(&[6])?;
writer.write_all(&addr.ip().octets())?;
}
};
writer.write_all(&self.port().to_be_bytes())
}
}

View File

@@ -16,7 +16,7 @@ use jukebox_song::JukeboxSong;
use paint::Painting;
use pig::PigVariant;
use pumpkin_protocol::java::client::config::RegistryEntry;
use pumpkin_util::resource_location::ResourceLocation;
use pumpkin_util::{read_data_from_file, resource_location::ResourceLocation};
use serde::{Deserialize, Serialize};
use trim_material::TrimMaterial;
use trim_pattern::TrimPattern;
@@ -40,10 +40,8 @@ mod trim_material;
mod trim_pattern;
mod wolf;
pub static SYNCED_REGISTRIES: LazyLock<SyncedRegistry> = LazyLock::new(|| {
serde_json::from_str(include_str!("../../assets/synced_registries.json"))
.expect("Could not parse synced_registries.json registry.")
});
pub static SYNCED_REGISTRIES: LazyLock<SyncedRegistry> =
LazyLock::new(|| read_data_from_file!("../../assets/synced_registries.json"));
pub struct Registry {
pub registry_id: ResourceLocation,

View File

@@ -1,6 +1,5 @@
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Debug, PartialEq, Eq)]
pub struct ParseGameModeError;
@@ -13,6 +12,17 @@ pub enum GameMode {
Spectator = 3,
}
impl GameMode {
pub fn to_str(&self) -> &'static str {
match self {
Self::Survival => "Survival",
Self::Creative => "Creative",
Self::Adventure => "Adventure",
Self::Spectator => "Spectator",
}
}
}
impl TryFrom<i8> for GameMode {
type Error = ();

View File

@@ -47,9 +47,8 @@ macro_rules! global_path {
#[macro_export]
macro_rules! read_data_from_file {
($path:expr) => {{
use std::fs;
use $crate::global_path;
serde_json::from_str(&fs::read_to_string(global_path!($path)).expect("no data file"))
serde_json::from_str(&std::fs::read_to_string(global_path!($path)).expect("no data file"))
.expect("failed to decode data")
}};
}

View File

@@ -69,10 +69,7 @@ pub const fn smallest_encompassing_power_of_two(value: u32) -> u32 {
}
#[inline]
pub fn floor_div<T>(x: T, y: T) -> T
where
T: PrimInt + Zero + One,
{
pub fn floor_div<T: PrimInt + Zero + One>(x: T, y: T) -> T {
let div = x / y;
if (x ^ y) < T::zero() && div * y != x {
div - T::one()
@@ -82,18 +79,12 @@ where
}
#[inline]
pub fn square<T>(n: T) -> T
where
T: Float,
{
pub fn square<T: Float>(n: T) -> T {
n * n
}
#[inline]
pub fn floor_mod<T>(x: T, y: T) -> T
where
T: PrimInt + Zero,
{
pub fn floor_mod<T: PrimInt + Zero>(x: T, y: T) -> T {
let rem = x % y;
if (x ^ y) < T::zero() && rem != T::zero() {
rem + y
@@ -103,26 +94,17 @@ where
}
#[inline]
pub fn map<T>(value: T, old_start: T, old_end: T, new_start: T, new_end: T) -> T
where
T: Float,
{
pub fn map<T: Float>(value: T, old_start: T, old_end: T, new_start: T, new_end: T) -> T {
lerp(lerp_progress(value, old_start, old_end), new_start, new_end)
}
#[inline]
pub fn lerp<T>(delta: T, start: T, end: T) -> T
where
T: Float,
{
pub fn lerp<T: Float>(delta: T, start: T, end: T) -> T {
start + delta * (end - start)
}
#[inline]
pub fn lerp_progress<T>(value: T, start: T, end: T) -> T
where
T: Float,
{
pub fn lerp_progress<T: Float>(value: T, start: T, end: T) -> T {
(value - start) / (end - start)
}

View File

@@ -7,7 +7,7 @@ use std::hash::Hash;
use crate::math::vector2::Vector2;
use num_traits::Euclid;
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
pub struct BlockPosIterator {
start_x: i32,
@@ -327,10 +327,7 @@ impl BlockPos {
}
impl Serialize for BlockPos {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let long = ((self.0.x as i64 & 0x3FFFFFF) << 38)
| ((self.0.z as i64 & 0x3FFFFFF) << 12)
| (self.0.y as i64 & 0xFFF);
@@ -339,20 +336,14 @@ impl Serialize for BlockPos {
}
impl<'de> Deserialize<'de> for BlockPos {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor;
impl serde::de::Visitor<'_> for Visitor {
type Value = BlockPos;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("An i64 int")
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<Self::Value, E> {
Ok(BlockPos(Vector3 {
x: (v >> 38) as i32,
y: (v << 52 >> 52) as i32,

View File

@@ -122,10 +122,7 @@ pub const fn to_chunk_pos(vec: &Vector2<i32>) -> Vector2<i32> {
}
impl serde::Serialize for Vector2<f32> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut buf = Vec::with_capacity(size_of::<Vector2<f32>>());
buf.put_f32(self.x);
buf.put_f32(self.y);

View File

@@ -221,10 +221,7 @@ impl<T> From<Vector3<T>> for (T, T, T) {
}
}
impl<T: Math + Copy> Vector3<T>
where
T: Into<f64>,
{
impl<T: Math + Copy + Into<f64>> Vector3<T> {
pub fn to_f64(&self) -> Vector3<f64> {
Vector3 {
x: self.x.into(),
@@ -234,10 +231,7 @@ where
}
}
impl<T: Math + Copy> Vector3<T>
where
T: Into<f64>,
{
impl<T: Math + Copy + Into<f64>> Vector3<T> {
pub fn to_i32(&self) -> Vector3<i32> {
let x: f64 = self.x.into();
let y: f64 = self.y.into();
@@ -259,10 +253,7 @@ where
}
}
impl<T: Math + Copy> Vector3<T>
where
T: Into<f64>,
{
impl<T: Math + Copy + Into<f64>> Vector3<T> {
pub fn to_block_pos(&self) -> BlockPos {
BlockPos(self.to_i32())
}
@@ -286,10 +277,7 @@ impl Math for i64 {}
impl Math for u8 {}
impl<'de> serde::Deserialize<'de> for Vector3<i32> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Vector3Visitor;
impl<'de> serde::de::Visitor<'de> for Vector3Visitor {
@@ -299,10 +287,10 @@ impl<'de> serde::Deserialize<'de> for Vector3<i32> {
formatter.write_str("a valid Vector<i32>")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
fn visit_seq<A: serde::de::SeqAccess<'de>>(
self,
mut seq: A,
) -> Result<Self::Value, A::Error> {
if let Some(x) = seq.next_element::<i32>()? {
if let Some(y) = seq.next_element::<i32>()? {
if let Some(z) = seq.next_element::<i32>()? {
@@ -319,10 +307,7 @@ impl<'de> serde::Deserialize<'de> for Vector3<i32> {
}
impl<'de> serde::Deserialize<'de> for Vector3<f32> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Vector3Visitor;
impl<'de> serde::de::Visitor<'de> for Vector3Visitor {
@@ -332,10 +317,10 @@ impl<'de> serde::Deserialize<'de> for Vector3<f32> {
formatter.write_str("a valid Vector<32>")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
fn visit_seq<A: serde::de::SeqAccess<'de>>(
self,
mut seq: A,
) -> Result<Self::Value, A::Error> {
if let Some(x) = seq.next_element::<f32>()? {
if let Some(y) = seq.next_element::<f32>()? {
if let Some(z) = seq.next_element::<f32>()? {
@@ -352,10 +337,7 @@ impl<'de> serde::Deserialize<'de> for Vector3<f32> {
}
impl<'de> serde::Deserialize<'de> for Vector3<f64> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Vector3Visitor;
impl<'de> serde::de::Visitor<'de> for Vector3Visitor {
@@ -365,10 +347,10 @@ impl<'de> serde::Deserialize<'de> for Vector3<f64> {
formatter.write_str("a valid Vector<f64>")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
fn visit_seq<A: serde::de::SeqAccess<'de>>(
self,
mut seq: A,
) -> Result<Self::Value, A::Error> {
if let Some(x) = seq.next_element::<f64>()? {
if let Some(y) = seq.next_element::<f64>()? {
if let Some(z) = seq.next_element::<f64>()? {
@@ -385,10 +367,7 @@ impl<'de> serde::Deserialize<'de> for Vector3<f64> {
}
impl serde::Serialize for Vector3<f32> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut buf = Vec::new();
buf.put_f32(self.x);
buf.put_f32(self.y);
@@ -398,10 +377,7 @@ impl serde::Serialize for Vector3<f32> {
}
impl serde::Serialize for Vector3<f64> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut buf = Vec::new();
buf.put_f64(self.x);
buf.put_f64(self.y);
@@ -411,10 +387,7 @@ impl serde::Serialize for Vector3<f64> {
}
impl serde::Serialize for Vector3<i16> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut buf = Vec::new();
buf.put_i16(self.x);
buf.put_i16(self.y);
@@ -424,10 +397,7 @@ impl serde::Serialize for Vector3<i16> {
}
impl serde::Serialize for Vector3<i32> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut buf = Vec::new();
buf.put_i32(self.x);
buf.put_i32(self.y);

View File

@@ -15,9 +15,9 @@ pub struct PerlinNoiseSampler {
impl PerlinNoiseSampler {
pub fn new(random: &mut impl RandomImpl) -> Self {
let x_origin = random.next_f64() * 256f64;
let y_origin = random.next_f64() * 256f64;
let z_origin = random.next_f64() * 256f64;
let x_origin = random.next_f64() * 256.0;
let y_origin = random.next_f64() * 256.0;
let z_origin = random.next_f64() * 256.0;
let mut permutation = [0u8; 256];
@@ -41,7 +41,7 @@ impl PerlinNoiseSampler {
#[inline]
pub fn sample_flat_y(&self, x: f64, y: f64, z: f64) -> f64 {
self.sample_no_fade(x, y, z, 0f64, 0f64)
self.sample_no_fade(x, y, z, 0.0, 0.0)
}
pub fn sample_no_fade(&self, x: f64, y: f64, z: f64, y_scale: f64, y_max: f64) -> f64 {
@@ -57,15 +57,15 @@ impl PerlinNoiseSampler {
let y_dec = true_y - y_floor;
let z_dec = true_z - z_floor;
let y_noise = if y_scale != 0f64 {
let raw_y_dec = if y_max >= 0f64 && y_max < y_dec {
let y_noise = if y_scale != 0.0 {
let raw_y_dec = if y_max >= 0.0 && y_max < y_dec {
y_max
} else {
y_dec
};
(raw_y_dec / y_scale + 1E-7f32 as f64).floor() * y_scale
(raw_y_dec / y_scale + 1E-7).floor() * y_scale
} else {
0f64
0.0
};
self.sample(
@@ -86,7 +86,7 @@ impl PerlinNoiseSampler {
#[inline]
fn perlin_fade(value: f64) -> f64 {
value * value * value * (value * (value * 6f64 - 15f64) + 10f64)
value * value * value * (value * (value * 6.0 - 15.0) + 10.0)
}
#[inline]
@@ -114,17 +114,17 @@ impl PerlinNoiseSampler {
let n = self.map(j + y + 1);
let d = Self::grad(self.map(k + z), local_x, local_y, local_z);
let e = Self::grad(self.map(m + z), local_x - 1f64, local_y, local_z);
let f = Self::grad(self.map(l + z), local_x, local_y - 1f64, local_z);
let g = Self::grad(self.map(n + z), local_x - 1f64, local_y - 1f64, local_z);
let h = Self::grad(self.map(k + z + 1), local_x, local_y, local_z - 1f64);
let o = Self::grad(self.map(m + z + 1), local_x - 1f64, local_y, local_z - 1f64);
let p = Self::grad(self.map(l + z + 1), local_x, local_y - 1f64, local_z - 1f64);
let e = Self::grad(self.map(m + z), local_x - 1.0, local_y, local_z);
let f = Self::grad(self.map(l + z), local_x, local_y - 1.0, local_z);
let g = Self::grad(self.map(n + z), local_x - 1.0, local_y - 1.0, local_z);
let h = Self::grad(self.map(k + z + 1), local_x, local_y, local_z - 1.0);
let o = Self::grad(self.map(m + z + 1), local_x - 1.0, local_y, local_z - 1.0);
let p = Self::grad(self.map(l + z + 1), local_x, local_y - 1.0, local_z - 1.0);
let q = Self::grad(
self.map(n + z + 1),
local_x - 1f64,
local_y - 1f64,
local_z - 1f64,
local_x - 1.0,
local_y - 1.0,
local_z - 1.0,
);
let r = Self::perlin_fade(local_x);
let s = Self::perlin_fade(fade_local_y);
@@ -167,7 +167,7 @@ impl OctavePerlinNoiseSampler {
#[inline]
pub fn maintain_precision(value: f64) -> f64 {
value - (value / 3.3554432E7f64 + 0.5f64).floor() * 3.3554432E7f64
value - (value / 3.3554432E7 + 0.5).floor() * 3.3554432E7
}
pub fn calculate_amplitudes(octaves: &[i32]) -> (i32, Vec<f64>) {
@@ -180,11 +180,11 @@ impl OctavePerlinNoiseSampler {
let mut double_list: Vec<f64> = Vec::with_capacity(k as usize);
for _ in 0..k {
double_list.push(0f64)
double_list.push(0.0)
}
for l in octaves {
double_list[(l + i) as usize] = 1f64;
double_list[(l + i) as usize] = 1.0;
}
(-i, double_list)
@@ -205,7 +205,7 @@ impl OctavePerlinNoiseSampler {
let sampler = PerlinNoiseSampler::new(random);
if j >= 0 && j < i as i32 {
let d = amplitudes[j as usize];
if d != 0f64 {
if d != 0.0 {
samplers[j as usize] = Some(sampler);
}
}
@@ -213,7 +213,7 @@ impl OctavePerlinNoiseSampler {
for kx in (0..j as usize).rev() {
if kx < i {
let e = amplitudes[kx];
if e != 0f64 {
if e != 0.0 {
samplers[kx] = Some(PerlinNoiseSampler::new(random));
} else {
random.skip(262);
@@ -225,7 +225,7 @@ impl OctavePerlinNoiseSampler {
} else {
let splitter = random.next_splitter();
for k in 0..i {
if amplitudes[k] != 0f64 {
if amplitudes[k] != 0.0 {
let l = first_octave + k as i32;
samplers[k] = Some(PerlinNoiseSampler::new(
&mut splitter.split_string(&format!("octave_{l}")),
@@ -234,25 +234,25 @@ impl OctavePerlinNoiseSampler {
}
}
let mut persistence = 2f64.powi(i as i32 - 1) / (2f64.powi(i as i32) - 1f64);
let mut persistence = 2f64.powi(i as i32 - 1) / (2f64.powi(i as i32) - 1.0);
let mut lacunarity = 2f64.powi(-j);
let persistences: Vec<f64> = (0..amplitudes.len())
.map(|_| {
let result = persistence;
persistence /= 2f64;
persistence /= 2.0;
result
})
.collect();
let lacunarities: Vec<f64> = (0..amplitudes.len())
.map(|_| {
let result = lacunarity;
lacunarity *= 2f64;
lacunarity *= 2.0;
result
})
.collect();
let max_value = Self::get_total_amplitude_generic(2f64, &persistences, amplitudes);
let max_value = Self::get_total_amplitude_generic(2.0, &persistences, amplitudes);
let samplers = samplers
.into_iter()
@@ -318,14 +318,14 @@ mod tests {
let (start, amplitudes) = OctavePerlinNoiseSampler::calculate_amplitudes(&[1, 2, 3]);
assert_eq!(start, 1);
assert_eq!(amplitudes, [1f64, 1f64, 1f64]);
assert_eq!(amplitudes, [1.0, 1.0, 1.0]);
let sampler = OctavePerlinNoiseSampler::new(&mut rand, start, &amplitudes, false);
let first = sampler.samplers.first().unwrap();
assert_eq!(first.persistence, 0.5714285714285714f64);
assert_eq!(first.lacunarity, 2f64);
assert_eq!(sampler.max_value, 2f64);
assert_eq!(first.persistence, 0.5714285714285714);
assert_eq!(first.lacunarity, 2.0);
assert_eq!(sampler.max_value, 2.0);
let coords = [
(210.19539348148294, 203.08258445596215, 45.29925114984684),
@@ -347,13 +347,13 @@ mod tests {
let (start, amplitudes) = OctavePerlinNoiseSampler::calculate_amplitudes(&[0]);
assert_eq!(start, 0);
assert_eq!(amplitudes, [1f64]);
assert_eq!(amplitudes, [1.0]);
let sampler = OctavePerlinNoiseSampler::new(&mut rand, start, &amplitudes, true);
let first = sampler.samplers.first().unwrap();
assert_eq!(first.persistence, 1f64);
assert_eq!(first.lacunarity, 1f64);
assert_eq!(sampler.max_value, 2f64);
assert_eq!(first.persistence, 1.0);
assert_eq!(first.lacunarity, 1.0);
assert_eq!(sampler.max_value, 2.0);
let coords = [(226.220117499588, 32.67924779023767, 202.84067325597647)];
@@ -827,7 +827,7 @@ mod tests {
for (x, y, z, sample) in expected_data {
let scale = 0.005;
let max_y = scale * 2f64;
let max_y = scale * 2.0;
let result = sampler.sample_no_fade(
x as f64 * scale,
y as f64 * scale,

View File

@@ -95,8 +95,8 @@ impl SimplexNoiseSampler {
let n = h - l as f64 + Self::UNSKEW_FACTOR_2D;
let o = k - m as f64 + Self::UNSKEW_FACTOR_2D;
let p = 2f64 * Self::UNSKEW_FACTOR_2D + (h - 1f64);
let q = 2f64 * Self::UNSKEW_FACTOR_2D + (k - 1f64);
let p = 2.0 * Self::UNSKEW_FACTOR_2D + (h - 1.0);
let q = 2.0 * Self::UNSKEW_FACTOR_2D + (k - 1.0);
let r = i & 0xFF;
let s = j & 0xFF;
@@ -105,21 +105,21 @@ impl SimplexNoiseSampler {
let u = self.map(r.wrapping_add(l).wrapping_add(self.map(s.wrapping_add(m)))) % 12;
let v = self.map(r.wrapping_add(1).wrapping_add(self.map(s.wrapping_add(1)))) % 12;
let w = Self::grad(t as usize, h, k, 0f64, 0.5f64);
let z = Self::grad(u as usize, n, o, 0f64, 0.5f64);
let aa = Self::grad(v as usize, p, q, 0f64, 0.5f64);
let w = Self::grad(t as usize, h, k, 0.0, 0.5);
let z = Self::grad(u as usize, n, o, 0.0, 0.5);
let aa = Self::grad(v as usize, p, q, 0.0, 0.5);
70f64 * (w + z + aa)
70.0 * (w + z + aa)
}
pub fn sample_3d(&self, x: f64, y: f64, z: f64) -> f64 {
let e = (x + y + z) * 0.3333333333333333f64;
let e = (x + y + z) * 0.3333333333333333;
let i = (x + e).floor() as i32;
let j = (y + e).floor() as i32;
let k = (z + e).floor() as i32;
let g = (i.wrapping_add(j).wrapping_add(k)) as f64 * 0.16666666666666666f64;
let g = (i.wrapping_add(j).wrapping_add(k)) as f64 * 0.16666666666666666;
let h = i as f64 - g;
let l = j as f64 - g;
let m = k as f64 - g;
@@ -144,17 +144,17 @@ impl SimplexNoiseSampler {
(0, 1, 0, 1, 1, 0)
};
let w = n - q as f64 + 0.16666666666666666f64;
let aa = o - r as f64 + 0.16666666666666666f64;
let ab = p - s as f64 + 0.16666666666666666f64;
let w = n - q as f64 + 0.16666666666666666;
let aa = o - r as f64 + 0.16666666666666666;
let ab = p - s as f64 + 0.16666666666666666;
let ac = n - t as f64 + 0.3333333333333333f64;
let ad = o - u as f64 + 0.3333333333333333f64;
let ae = p - v as f64 + 0.3333333333333333f64;
let ac = n - t as f64 + 0.3333333333333333;
let ad = o - u as f64 + 0.3333333333333333;
let ae = p - v as f64 + 0.3333333333333333;
let af = n - 1f64 + 0.5f64;
let ag = o - 1f64 + 0.5f64;
let ah = p - 1f64 + 0.5f64;
let af = n - 1.0 + 0.5;
let ag = o - 1.0 + 0.5;
let ah = p - 1.0 + 0.5;
let ai = i & 0xFF;
let aj = j & 0xFF;
@@ -186,12 +186,12 @@ impl SimplexNoiseSampler {
),
) % 12;
let ap = Self::grad(al as usize, n, o, p, 0.6f64);
let aq = Self::grad(am as usize, w, aa, ab, 0.6f64);
let ar = Self::grad(an as usize, ac, ad, ae, 0.6f64);
let az = Self::grad(ao as usize, af, ag, ah, 0.6f64);
let ap = Self::grad(al as usize, n, o, p, 0.6);
let aq = Self::grad(am as usize, w, aa, ab, 0.6);
let ar = Self::grad(an as usize, ac, ad, ae, 0.6);
let az = Self::grad(ao as usize, af, ag, ah, 0.6);
32f64 * (ap + aq + ar + az)
32.0 * (ap + aq + ar + az)
}
}
@@ -247,26 +247,26 @@ impl OctaveSimplexNoiseSampler {
Self {
octave_samplers: samplers,
persistence: 1f64 / (2f64.pow(k) - 1f64),
lacunarity: 2f64.pow(j),
persistence: 1.0 / (2.0.pow(k) - 1.0),
lacunarity: 2.0.pow(j),
}
}
pub fn sample(&self, x: f64, y: f64, use_origin: bool) -> f64 {
let mut d = 0f64;
let mut d = 0.0;
let mut e = self.lacunarity;
let mut f = self.persistence;
for sampler in self.octave_samplers.iter() {
if let Some(sampler) = sampler {
d += sampler.sample_2d(
x * e + if use_origin { sampler.x_origin } else { 0f64 },
y * e + if use_origin { sampler.y_origin } else { 0f64 },
x * e + if use_origin { sampler.x_origin } else { 0.0 },
y * e + if use_origin { sampler.y_origin } else { 0.0 },
) * f;
}
e /= 2f64;
f *= 2f64;
e /= 2.0;
f *= 2.0;
}
d
@@ -286,7 +286,7 @@ mod octave_simplex_noise_sampler_test {
assert_eq!(rand.next_i32(), 1394613419);
let sampler = OctaveSimplexNoiseSampler::new(&mut rand, &[-1, 1, 0]);
assert_eq!(sampler.lacunarity, 2f64);
assert_eq!(sampler.lacunarity, 2.0);
assert_eq!(sampler.persistence, 0.14285714285714285);
let values = [
@@ -421,9 +421,9 @@ mod simplex_noise_sampler_test {
let mut rand = Xoroshiro::from_seed(111);
assert_eq!(rand.next_i32(), -1467508761);
let sampler = SimplexNoiseSampler::new(&mut rand);
assert_eq!(sampler.x_origin, 48.58072036717974f64);
assert_eq!(sampler.y_origin, 110.73235882678037f64);
assert_eq!(sampler.z_origin, 65.26438852860176f64);
assert_eq!(sampler.x_origin, 48.58072036717974);
assert_eq!(sampler.y_origin, 110.73235882678037);
assert_eq!(sampler.z_origin, 65.26438852860176);
let permutation: [u8; 256] = [
159, 113, 41, 143, 203, 123, 95, 177, 25, 79, 229, 219, 194, 60, 130, 14, 83, 99, 24,

Some files were not shown because too many files have changed in this diff Show More