mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
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:
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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.
|
||||
|
||||
BIN
assets/bedrock_block_states.nbt
Normal file
BIN
assets/bedrock_block_states.nbt
Normal file
Binary file not shown.
@@ -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]
|
||||
|
||||
@@ -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!(
|
||||
|
||||
@@ -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"]))
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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")
|
||||
);
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
)?))
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
10
pumpkin-protocol/src/bedrock/client/chunk_radius_update.rs
Normal file
10
pumpkin-protocol/src/bedrock/client/chunk_radius_update.rs
Normal 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,
|
||||
}
|
||||
16
pumpkin-protocol/src/bedrock/client/container_open.rs
Normal file
16
pumpkin-protocol/src/bedrock/client/container_open.rs
Normal 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,
|
||||
}
|
||||
54
pumpkin-protocol/src/bedrock/client/creative_content.rs
Normal file
54
pumpkin-protocol/src/bedrock/client/creative_content.rs
Normal 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,
|
||||
}
|
||||
36
pumpkin-protocol/src/bedrock/client/disconnect_player.rs
Normal file
36
pumpkin-protocol/src/bedrock/client/disconnect_player.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
18
pumpkin-protocol/src/bedrock/client/inventory_content.rs
Normal file
18
pumpkin-protocol/src/bedrock/client/inventory_content.rs
Normal 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,
|
||||
}
|
||||
79
pumpkin-protocol/src/bedrock/client/level_chunk.rs
Normal file
79
pumpkin-protocol/src/bedrock/client/level_chunk.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
19
pumpkin-protocol/src/bedrock/client/move_player.rs
Normal file
19
pumpkin-protocol/src/bedrock/client/move_player.rs
Normal 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,
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
11
pumpkin-protocol/src/bedrock/client/player_hotbar.rs
Normal file
11
pumpkin-protocol/src/bedrock/client/player_hotbar.rs
Normal 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,
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
15
pumpkin-protocol/src/bedrock/client/set_time.rs
Normal file
15
pumpkin-protocol/src/bedrock/client/set_time.rs
Normal 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) }
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
26
pumpkin-protocol/src/bedrock/client/update_artributes.rs
Normal file
26
pumpkin-protocol/src/bedrock/client/update_artributes.rs
Normal 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,
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
82
pumpkin-protocol/src/bedrock/network_item.rs
Normal file
82
pumpkin-protocol/src/bedrock/network_item.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
12
pumpkin-protocol/src/bedrock/server/container_close.rs
Normal file
12
pumpkin-protocol/src/bedrock/server/container_close.rs
Normal 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,
|
||||
}
|
||||
41
pumpkin-protocol/src/bedrock/server/interaction.rs
Normal file
41
pumpkin-protocol/src/bedrock/server/interaction.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
110
pumpkin-protocol/src/bedrock/server/player_auth_input.rs
Normal file
110
pumpkin-protocol/src/bedrock/server/player_auth_input.rs
Normal 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,
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
10
pumpkin-protocol/src/bedrock/server/request_chunk_radius.rs
Normal file
10
pumpkin-protocol/src/bedrock/server/request_chunk_radius.rs
Normal 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,
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
159
pumpkin-protocol/src/bedrock/server/text.rs
Normal file
159
pumpkin-protocol/src/bedrock/server/text.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
22
pumpkin-protocol/src/codec/u24_type.rs
Normal file
22
pumpkin-protocol/src/codec/u24_type.rs
Normal 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])))
|
||||
}
|
||||
}
|
||||
11
pumpkin-protocol/src/codec/uuid.rs
Normal file
11
pumpkin-protocol/src/codec/uuid.rs
Normal 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())
|
||||
}
|
||||
}
|
||||
@@ -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, ""))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, ""))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!(),
|
||||
};
|
||||
|
||||
@@ -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))?;
|
||||
|
||||
@@ -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"))?;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
197
pumpkin-protocol/src/serial/deserializer.rs
Normal file
197
pumpkin-protocol/src/serial/deserializer.rs
Normal 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")),
|
||||
}
|
||||
}
|
||||
}
|
||||
18
pumpkin-protocol/src/serial/mod.rs
Normal file
18
pumpkin-protocol/src/serial/mod.rs
Normal 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")
|
||||
}
|
||||
}
|
||||
167
pumpkin-protocol/src/serial/serializer.rs
Normal file
167
pumpkin-protocol/src/serial/serializer.rs
Normal 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())
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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 = ();
|
||||
|
||||
|
||||
@@ -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")
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, &litudes, 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, &litudes, 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,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user