1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

Merge branch 'main' into 1.19.3

This commit is contained in:
mat 2022-10-30 15:37:07 -05:00
commit a3c5fdf13f
81 changed files with 15536 additions and 34253 deletions

38
Cargo.lock generated
View file

@ -100,7 +100,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "azalea"
version = "0.2.4"
version = "0.3.0"
dependencies = [
"anyhow",
"async-trait",
@ -114,7 +114,7 @@ dependencies = [
[[package]]
name = "azalea-auth"
version = "0.2.2"
version = "0.3.0"
dependencies = [
"azalea-buf",
"azalea-crypto",
@ -132,7 +132,7 @@ dependencies = [
[[package]]
name = "azalea-block"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"azalea-block-macros",
"azalea-buf",
@ -140,7 +140,7 @@ dependencies = [
[[package]]
name = "azalea-block-macros"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
@ -149,11 +149,11 @@ dependencies = [
[[package]]
name = "azalea-brigadier"
version = "0.2.0"
version = "0.3.0"
[[package]]
name = "azalea-buf"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"azalea-buf-macros",
"byteorder",
@ -165,7 +165,7 @@ dependencies = [
[[package]]
name = "azalea-buf-macros"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
@ -174,7 +174,7 @@ dependencies = [
[[package]]
name = "azalea-chat"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"azalea-buf",
"azalea-language",
@ -185,7 +185,7 @@ dependencies = [
[[package]]
name = "azalea-client"
version = "0.2.2"
version = "0.3.0"
dependencies = [
"anyhow",
"azalea-auth",
@ -205,7 +205,7 @@ dependencies = [
[[package]]
name = "azalea-core"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"azalea-buf",
"azalea-chat",
@ -215,7 +215,7 @@ dependencies = [
[[package]]
name = "azalea-crypto"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"aes",
"azalea-buf",
@ -230,7 +230,7 @@ dependencies = [
[[package]]
name = "azalea-language"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"lazy_static",
"serde",
@ -239,7 +239,7 @@ dependencies = [
[[package]]
name = "azalea-nbt"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"ahash",
"azalea-buf",
@ -252,7 +252,7 @@ dependencies = [
[[package]]
name = "azalea-physics"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"azalea-block",
"azalea-core",
@ -263,7 +263,7 @@ dependencies = [
[[package]]
name = "azalea-protocol"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"async-compression",
"async-recursion",
@ -295,7 +295,7 @@ dependencies = [
[[package]]
name = "azalea-protocol-macros"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
@ -304,7 +304,7 @@ dependencies = [
[[package]]
name = "azalea-registry"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"azalea-buf",
"azalea-registry-macros",
@ -312,7 +312,7 @@ dependencies = [
[[package]]
name = "azalea-registry-macros"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
@ -321,7 +321,7 @@ dependencies = [
[[package]]
name = "azalea-world"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"azalea-block",
"azalea-buf",

21
LICENSE.md Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 mat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,5 +1,7 @@
# Azalea
[![docs.rs](https://img.shields.io/docsrs/azalea)](https://docs.rs/azalea)
A collection of Rust crates for making Minecraft bots, clients, and tools.
<p align="center">

View file

@ -3,23 +3,24 @@ description = "A port of Mojang's Authlib and launcher authentication."
edition = "2021"
license = "MIT"
name = "azalea-auth"
version = "0.2.2"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-auth"
version = "0.3.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = { path = "../azalea-buf", version = "^0.2.0" }
azalea-crypto = { path = "../azalea-crypto", version = "^0.2.0" }
chrono = { version = "0.4.22", default-features = false }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-crypto = {path = "../azalea-crypto", version = "^0.3.0" }
chrono = {version = "0.4.22", default-features = false}
log = "0.4.17"
num-bigint = "0.4.3"
reqwest = { version = "0.11.12", features = ["json"] }
serde = { version = "1.0.145", features = ["derive"] }
reqwest = {version = "0.11.12", features = ["json"]}
serde = {version = "1.0.145", features = ["derive"]}
serde_json = "1.0.86"
thiserror = "1.0.37"
tokio = { version = "1.21.2", features = ["fs"] }
tokio = {version = "1.21.2", features = ["fs"]}
uuid = "^1.1.2"
[dev-dependencies]
env_logger = "0.9.1"
tokio = { version = "1.21.2", features = ["full"] }
tokio = {version = "1.21.2", features = ["full"]}

View file

@ -15,5 +15,5 @@ async fn main() {
)
.await
.unwrap();
println!("{:?}", auth_result);
println!("{auth_result:?}");
}

View file

@ -336,7 +336,7 @@ async fn auth_with_xbox_live(
"SiteName": "user.auth.xboxlive.com",
// i thought this was supposed to be d={} but it doesn't work for
// me when i add it ??????
"RpsTicket": format!("{}", access_token)
"RpsTicket": format!("{access_token}")
},
"RelyingParty": "http://auth.xboxlive.com",
"TokenType": "JWT"
@ -359,7 +359,7 @@ async fn auth_with_xbox_live(
// not_after looks like 2020-12-21T19:52:08.4463796Z
let expires_at = DateTime::parse_from_rfc3339(&res.not_after)
.map_err(|e| XboxLiveAuthError::InvalidExpiryDate(format!("{}: {}", res.not_after, e)))?
.map_err(|e| XboxLiveAuthError::InvalidExpiryDate(format!("{}: {e}", res.not_after)))?
.with_timezone(&Utc)
.timestamp() as u64;
Ok(ExpiringValue {
@ -416,7 +416,7 @@ async fn auth_with_minecraft(
.post("https://api.minecraftservices.com/authentication/login_with_xbox")
.header("Accept", "application/json")
.json(&json!({
"identityToken": format!("XBL3.0 x={};{}", user_hash, xsts_token)
"identityToken": format!("XBL3.0 x={user_hash};{xsts_token}")
}))
.send()
.await?
@ -444,10 +444,7 @@ async fn check_ownership(
) -> Result<bool, CheckOwnershipError> {
let res = client
.get("https://api.minecraftservices.com/entitlements/mcstore")
.header(
"Authorization",
format!("Bearer {}", minecraft_access_token),
)
.header("Authorization", format!("Bearer {minecraft_access_token}"))
.send()
.await?
.json::<GameOwnershipResponse>()
@ -472,10 +469,7 @@ async fn get_profile(
) -> Result<ProfileResponse, GetProfileError> {
let res = client
.get("https://api.minecraftservices.com/minecraft/profile")
.header(
"Authorization",
format!("Bearer {}", minecraft_access_token),
)
.header("Authorization", format!("Bearer {minecraft_access_token}"))
.send()
.await?
.json::<ProfileResponse>()

View file

@ -3,12 +3,13 @@ description = "Representation of Minecraft block states."
edition = "2021"
license = "MIT"
name = "azalea-block"
version = "0.2.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-block"
version = "0.3.0"
[lib]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-block-macros = {path = "./azalea-block-macros", version = "^0.2.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.2.0" }
azalea-block-macros = {path = "./azalea-block-macros", version = "^0.3.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }

View file

@ -3,7 +3,8 @@ description = "Proc macros used by azalea-block."
edition = "2021"
license = "MIT"
name = "azalea-block-macros"
version = "0.2.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-block/azalea-block-macros"
version = "0.3.0"
[lib]
proc-macro = true

View file

@ -317,7 +317,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
// }
let property_variants = properties_map
.get(property_name)
.unwrap_or_else(|| panic!("Property '{}' not found", property_name))
.unwrap_or_else(|| panic!("Property '{property_name}' not found"))
.clone();
block_properties_vec.push(property_variants);
}
@ -354,7 +354,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
previous_names.push(property_name.clone());
if let Some(index) = index {
// property_name.push_str(&format!("_{}", &index.to_string()));
write!(property_name, "_{}", index).unwrap();
write!(property_name, "_{index}").unwrap();
}
properties_with_name.push(PropertyWithNameAndDefault {
name: Ident::new(&property_name, proc_macro2::Span::call_site()),
@ -391,7 +391,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
proc_macro2::Span::call_site(),
);
let block_struct_name = Ident::new(
&format!("{}Block", block_name_pascal_case),
&format!("{block_name_pascal_case}Block"),
proc_macro2::Span::call_site(),
);

View file

@ -3,7 +3,8 @@ description = "A port of Mojang's Brigadier command parsing and dispatching libr
edition = "2021"
license = "MIT"
name = "azalea-brigadier"
version = "0.2.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-brigadier"
version = "0.3.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -45,35 +45,35 @@ impl fmt::Debug for BuiltInExceptions {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BuiltInExceptions::DoubleTooSmall { found, min } => {
write!(f, "Double must not be less than {}, found {}", min, found)
write!(f, "Double must not be less than {min}, found {found}")
}
BuiltInExceptions::DoubleTooBig { found, max } => {
write!(f, "Double must not be more than {}, found {}", max, found)
write!(f, "Double must not be more than {max}, found {found}")
}
BuiltInExceptions::FloatTooSmall { found, min } => {
write!(f, "Float must not be less than {}, found {}", min, found)
write!(f, "Float must not be less than {min}, found {found}")
}
BuiltInExceptions::FloatTooBig { found, max } => {
write!(f, "Float must not be more than {}, found {}", max, found)
write!(f, "Float must not be more than {max}, found {found}")
}
BuiltInExceptions::IntegerTooSmall { found, min } => {
write!(f, "Integer must not be less than {}, found {}", min, found)
write!(f, "Integer must not be less than {min}, found {found}")
}
BuiltInExceptions::IntegerTooBig { found, max } => {
write!(f, "Integer must not be more than {}, found {}", max, found)
write!(f, "Integer must not be more than {max}, found {found}")
}
BuiltInExceptions::LongTooSmall { found, min } => {
write!(f, "Long must not be less than {}, found {}", min, found)
write!(f, "Long must not be less than {min}, found {found}")
}
BuiltInExceptions::LongTooBig { found, max } => {
write!(f, "Long must not be more than {}, found {}", max, found)
write!(f, "Long must not be more than {max}, found {found}")
}
BuiltInExceptions::LiteralIncorrect { expected } => {
write!(f, "Expected literal {}", expected)
write!(f, "Expected literal {expected}")
}
BuiltInExceptions::ReaderExpectedStartOfQuote => {
@ -97,25 +97,25 @@ impl fmt::Debug for BuiltInExceptions {
)
}
BuiltInExceptions::ReaderInvalidInt { value } => {
write!(f, "Invalid Integer '{}'", value)
write!(f, "Invalid Integer '{value}'")
}
BuiltInExceptions::ReaderExpectedInt => {
write!(f, "Expected Integer")
}
BuiltInExceptions::ReaderInvalidLong { value } => {
write!(f, "Invalid long '{}'", value)
write!(f, "Invalid long '{value}'")
}
BuiltInExceptions::ReaderExpectedLong => {
write!(f, "Expected long")
}
BuiltInExceptions::ReaderInvalidDouble { value } => {
write!(f, "Invalid double '{}'", value)
write!(f, "Invalid double '{value}'")
}
BuiltInExceptions::ReaderExpectedDouble => {
write!(f, "Expected double")
}
BuiltInExceptions::ReaderInvalidFloat { value } => {
write!(f, "Invalid Float '{}'", value)
write!(f, "Invalid Float '{value}'")
}
BuiltInExceptions::ReaderExpectedFloat => {
write!(f, "Expected Float")
@ -124,7 +124,7 @@ impl fmt::Debug for BuiltInExceptions {
write!(f, "Expected bool")
}
BuiltInExceptions::ReaderExpectedSymbol { symbol } => {
write!(f, "Expected '{}'", symbol)
write!(f, "Expected '{symbol}'")
}
BuiltInExceptions::DispatcherUnknownCommand => {
@ -140,7 +140,7 @@ impl fmt::Debug for BuiltInExceptions {
)
}
BuiltInExceptions::DispatcherParseException { message } => {
write!(f, "Could not parse command: {}", message)
write!(f, "Could not parse command: {message}")
}
}
}
@ -148,12 +148,12 @@ impl fmt::Debug for BuiltInExceptions {
impl BuiltInExceptions {
pub fn create(self) -> CommandSyntaxException {
let message = Message::from(format!("{:?}", self));
let message = Message::from(format!("{self:?}"));
CommandSyntaxException::create(self, message)
}
pub fn create_with_context(self, reader: &StringReader) -> CommandSyntaxException {
let message = Message::from(format!("{:?}", self));
let message = Message::from(format!("{self:?}"));
CommandSyntaxException::new(self, message, reader.string(), reader.cursor())
}
}

View file

@ -275,7 +275,7 @@ fn execute_redirected_multiple_times() {
child2.clone().unwrap().nodes[0].range,
child2.clone().unwrap().range
);
assert_eq!(child2.clone().unwrap().nodes[0].node, concrete_node);
assert_eq!(child2.unwrap().nodes[0].node, concrete_node);
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 42);
}
@ -406,5 +406,5 @@ fn get_path() {
fn find_node_doesnt_exist() {
let subject = CommandDispatcher::<()>::new();
assert_eq!(subject.find_node(&vec!["foo", "bar"]), None)
assert_eq!(subject.find_node(&["foo", "bar"]), None)
}

View file

@ -3,12 +3,13 @@ description = "Serialize and deserialize buffers from Minecraft."
edition = "2021"
license = "MIT"
name = "azalea-buf"
version = "0.2.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-buf"
version = "0.3.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.2.0" }
azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.3.0" }
byteorder = "^1.4.3"
serde_json = {version = "^1.0", optional = true}
thiserror = "^1.0.34"

View file

@ -3,7 +3,8 @@ description = "#[derive(McBuf)]"
edition = "2021"
license = "MIT"
name = "azalea-buf-macros"
version = "0.2.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-buf"
version = "0.3.0"
[lib]
proc-macro = true

View file

@ -78,7 +78,7 @@ mod tests {
let u = Uuid::parse_str("6536bfed-8695-48fd-83a1-ecd24cf2a0fd").unwrap();
let mut buf = Vec::new();
u.write_into(&mut buf).unwrap();
println!("{:?}", buf);
println!("{buf:?}");
assert_eq!(buf.len(), 16);
let u2 = Uuid::read_from(&mut Cursor::new(&buf)).unwrap();
assert_eq!(u, u2);

View file

@ -3,13 +3,14 @@ description = "Parse Minecraft chat messages."
edition = "2021"
license = "MIT"
name = "azalea-chat"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-chat"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = {path = "../azalea-buf", features = ["serde_json"], version = "^0.2.0" }
azalea-language = {path = "../azalea-language", version = "^0.2.0" }
azalea-buf = {path = "../azalea-buf", features = ["serde_json"], version = "^0.3.0" }
azalea-language = {path = "../azalea-language", version = "^0.3.0" }
lazy_static = "^1.4.0"
serde = "^1.0.130"
serde_json = "^1.0.72"

View file

@ -1,4 +1,4 @@
use crate::{component::Component, style::Style};
use crate::{style::Style, Component};
#[derive(Clone, Debug)]
pub struct BaseComponent {

View file

@ -13,6 +13,7 @@ use crate::{
translatable_component::{StringOrComponent, TranslatableComponent},
};
/// A chat component, basically anything you can see in chat.
#[derive(Clone, Debug)]
pub enum Component {
Text(TextComponent),
@ -57,7 +58,22 @@ impl Component {
Ok(None)
}
/// Convert this component into an ansi string
/// Convert this component into an
/// [ANSI string](https://en.wikipedia.org/wiki/ANSI_escape_code), so you
/// can print it to your terminal and get styling.
///
/// # Examples
///
/// ```rust
/// use azalea_chat::Component;
///
/// let component = Component::deserialize(&serde_json::json!({
/// "text": "Hello, world!",
/// "color": "red",
/// })).unwrap();
///
/// println!("{}", component.to_ansi());
/// ```
pub fn to_ansi(&self, default_style: Option<&Style>) -> String {
// default the default_style to white if it's not set
let default_style: &Style = default_style.unwrap_or(&DEFAULT_STYLE);
@ -186,7 +202,7 @@ impl<'de> Deserialize<'de> for Component {
nbt
} else {
return Err(de::Error::custom(
format!("Don't know how to turn {} into a Component", json).as_str(),
format!("Don't know how to turn {json} into a Component").as_str(),
));
};
let _separator = Component::parse_separator(&json).map_err(de::Error::custom)?;
@ -223,7 +239,7 @@ impl<'de> Deserialize<'de> for Component {
// ok so it's not an object, if it's an array deserialize every item
else if !json.is_array() {
return Err(de::Error::custom(
format!("Don't know how to turn {} into a Component", json).as_str(),
format!("Don't know how to turn {json} into a Component").as_str(),
));
}
let json_array = json.as_array().unwrap();

View file

@ -5,7 +5,9 @@
extern crate lazy_static;
pub mod base_component;
pub mod component;
mod component;
pub mod style;
pub mod text_component;
pub mod translatable_component;
pub use component::Component;

View file

@ -1,7 +1,8 @@
use std::fmt::Display;
use crate::{base_component::BaseComponent, component::Component, style::ChatFormatting};
use crate::{base_component::BaseComponent, style::ChatFormatting, Component};
/// A component that contains text that's the same in all locales.
#[derive(Clone, Debug)]
pub struct TextComponent {
pub base: BaseComponent,

View file

@ -1,8 +1,7 @@
use std::fmt::{self, Display, Formatter};
use crate::{
base_component::BaseComponent, component::Component, style::Style,
text_component::TextComponent,
base_component::BaseComponent, style::Style, text_component::TextComponent, Component,
};
#[derive(Clone, Debug)]
@ -11,6 +10,7 @@ pub enum StringOrComponent {
Component(Component),
}
/// A message whose content depends on the client's language.
#[derive(Clone, Debug)]
pub struct TranslatableComponent {
pub base: BaseComponent,
@ -134,8 +134,8 @@ impl Display for TranslatableComponent {
impl Display for StringOrComponent {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
match self {
StringOrComponent::String(s) => write!(f, "{}", s),
StringOrComponent::Component(c) => write!(f, "{}", c),
StringOrComponent::String(s) => write!(f, "{s}"),
StringOrComponent::Component(c) => write!(f, "{c}"),
}
}
}

View file

@ -1,6 +1,6 @@
use azalea_chat::{
component::Component,
style::{Ansi, ChatFormatting, TextColor},
Component,
};
use serde::Deserialize;
use serde_json::Value;

View file

@ -3,20 +3,21 @@ description = "A headless Minecraft client."
edition = "2021"
license = "MIT"
name = "azalea-client"
version = "0.2.2"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-client"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.59"
azalea-auth = { path = "../azalea-auth", version = "0.2.1" }
azalea-block = { path = "../azalea-block", version = "0.2.0" }
azalea-chat = { path = "../azalea-chat", version = "0.2.0" }
azalea-core = { path = "../azalea-core", version = "0.2.0" }
azalea-crypto = { path = "../azalea-crypto", version = "0.2.0" }
azalea-physics = { path = "../azalea-physics", version = "0.2.0" }
azalea-protocol = { path = "../azalea-protocol", version = "0.2.0" }
azalea-world = { path = "../azalea-world", version = "0.2.0" }
azalea-auth = { path = "../azalea-auth", version = "0.3.0" }
azalea-block = { path = "../azalea-block", version = "0.3.0" }
azalea-chat = { path = "../azalea-chat", version = "0.3.0" }
azalea-core = { path = "../azalea-core", version = "0.3.0" }
azalea-crypto = { path = "../azalea-crypto", version = "0.3.0" }
azalea-physics = { path = "../azalea-physics", version = "0.3.0" }
azalea-protocol = { path = "../azalea-protocol", version = "0.3.0" }
azalea-world = { path = "../azalea-world", version = "0.3.0" }
log = "0.4.17"
parking_lot = "0.12.1"
thiserror = "^1.0.34"

View file

@ -6,6 +6,18 @@ use uuid::Uuid;
/// Something that can join Minecraft servers.
///
/// To join a server using this account, use [`crate::Client::join`].
///
/// # Examples
///
/// ```rust,no_run
/// use azalea_client::Account;
///
/// # #[tokio::main]
/// # async fn main() {
/// let account = Account::microsoft("example@example.com").await;
/// // or Account::offline("example");
/// # }
/// ```
#[derive(Clone, Debug)]
pub struct Account {
/// The Minecraft username of the account.
@ -34,7 +46,13 @@ impl Account {
/// a key for the cache, but it's recommended to use the real email to
/// avoid confusion.
pub async fn microsoft(email: &str) -> Result<Self, azalea_auth::AuthError> {
let minecraft_dir = get_mc_dir::minecraft_dir().unwrap();
let minecraft_dir = get_mc_dir::minecraft_dir().expect(
format!(
"No {} environment variable found",
get_mc_dir::home_env_var()
)
.as_str(),
);
let auth_result = azalea_auth::auth(
email,
azalea_auth::AuthOpts {

View file

@ -1,6 +1,6 @@
use crate::{movement::MoveDirection, Account, Player};
use azalea_auth::game_profile::GameProfile;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_core::{ChunkPos, ResourceLocation, Vec3};
use azalea_protocol::{
connect::{Connection, ConnectionError, ReadConnection, WriteConnection},
@ -63,6 +63,7 @@ pub enum Event {
Packet(Box<ClientboundGamePacket>),
}
/// A chat packet, either a system message or a chat message.
#[derive(Debug, Clone)]
pub enum ChatPacket {
System(ClientboundSystemChatPacket),
@ -70,6 +71,7 @@ pub enum ChatPacket {
}
impl ChatPacket {
/// Get the message shown in chat for this packet.
pub fn message(&self) -> Component {
match self {
ChatPacket::System(p) => p.content.clone(),
@ -186,55 +188,48 @@ impl Client {
.await?;
let (conn, game_profile) = loop {
let packet_result = conn.read().await;
match packet_result {
Ok(packet) => match packet {
ClientboundLoginPacket::Hello(p) => {
debug!("Got encryption request");
let e = azalea_crypto::encrypt(&p.public_key, &p.nonce).unwrap();
let packet = conn.read().await?;
match packet {
ClientboundLoginPacket::Hello(p) => {
debug!("Got encryption request");
let e = azalea_crypto::encrypt(&p.public_key, &p.nonce).unwrap();
if let Some(access_token) = &account.access_token {
conn.authenticate(
access_token,
&account
.uuid
.expect("Uuid must be present if access token is present."),
e.secret_key,
p,
)
.await?;
}
conn.write(
ServerboundKeyPacket {
nonce_or_salt_signature: NonceOrSaltSignature::Nonce(
e.encrypted_nonce,
),
key_bytes: e.encrypted_public_key,
}
.get(),
if let Some(access_token) = &account.access_token {
conn.authenticate(
access_token,
&account
.uuid
.expect("Uuid must be present if access token is present."),
e.secret_key,
p,
)
.await?;
}
conn.set_encryption_key(e.secret_key);
}
ClientboundLoginPacket::LoginCompression(p) => {
debug!("Got compression request {:?}", p.compression_threshold);
conn.set_compression_threshold(p.compression_threshold);
}
ClientboundLoginPacket::GameProfile(p) => {
debug!("Got profile {:?}", p.game_profile);
break (conn.game(), p.game_profile);
}
ClientboundLoginPacket::LoginDisconnect(p) => {
debug!("Got disconnect {:?}", p);
}
ClientboundLoginPacket::CustomQuery(p) => {
debug!("Got custom query {:?}", p);
}
},
Err(e) => {
panic!("Error: {:?}", e);
conn.write(
ServerboundKeyPacket {
nonce_or_salt_signature: NonceOrSaltSignature::Nonce(e.encrypted_nonce),
key_bytes: e.encrypted_public_key,
}
.get(),
)
.await?;
conn.set_encryption_key(e.secret_key);
}
ClientboundLoginPacket::LoginCompression(p) => {
debug!("Got compression request {:?}", p.compression_threshold);
conn.set_compression_threshold(p.compression_threshold);
}
ClientboundLoginPacket::GameProfile(p) => {
debug!("Got profile {:?}", p.game_profile);
break (conn.game(), p.game_profile);
}
ClientboundLoginPacket::LoginDisconnect(p) => {
debug!("Got disconnect {:?}", p);
}
ClientboundLoginPacket::CustomQuery(p) => {
debug!("Got custom query {:?}", p);
}
}
};
@ -304,7 +299,7 @@ impl Client {
if IGNORE_ERRORS {
continue;
} else {
panic!("Error handling packet: {}", e);
panic!("Error handling packet: {e}");
}
}
},
@ -312,7 +307,7 @@ impl Client {
if IGNORE_ERRORS {
warn!("{}", e);
match e {
ReadPacketError::FrameSplitter { .. } => panic!("Error: {:?}", e),
ReadPacketError::FrameSplitter { .. } => panic!("Error: {e:?}"),
_ => continue,
}
} else {
@ -747,7 +742,6 @@ impl Client {
ClientboundGamePacket::SetCamera(_) => {}
ClientboundGamePacket::SetChunkCacheRadius(_) => {}
ClientboundGamePacket::SetDisplayObjective(_) => {}
ClientboundGamePacket::SetEntityMotion(_) => {}
ClientboundGamePacket::SetObjective(_) => {}
ClientboundGamePacket::SetPassengers(_) => {}
ClientboundGamePacket::SetPlayerTeam(_) => {}
@ -764,6 +758,7 @@ impl Client {
ClientboundGamePacket::DisguisedChat(_) => {}
ClientboundGamePacket::PlayerInfoRemove(_) => {}
ClientboundGamePacket::UpdateEnabledFeatures(_) => {}
ClientboundGamePacket::ContainerClose(_) => {}
}
Ok(())

View file

@ -10,25 +10,52 @@ use std::path::PathBuf;
/// Mac: `$HOME/Library/Application Support/minecraft`\
/// Linux: `$HOME/.minecraft`
///
/// Anywhere else it'll return None.
/// If the environment variable is not set, this will return `None`.
pub fn minecraft_dir() -> Option<PathBuf> {
let env_var = home_env_var();
let home = std::env::var(env_var).ok()?;
let path = PathBuf::from(home).join(minecraft_dir_relative());
Some(path)
}
/// Return the name of the environment variable that's used for the home folder
/// on the user's operating system.
pub fn home_env_var() -> &'static str {
#[cfg(target_os = "windows")]
{
let appdata = std::env::var("APPDATA").ok()?;
Some(PathBuf::from(appdata).join(".minecraft"))
"USERPROFILE"
}
#[cfg(target_os = "macos")]
{
let home = std::env::var("HOME").ok()?;
Some(PathBuf::from(home).join("Library/Application Support/minecraft"))
"HOME"
}
#[cfg(target_os = "linux")]
{
let home = std::env::var("HOME").ok()?;
Some(PathBuf::from(home).join(".minecraft"))
"HOME"
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
None
"HOME"
}
}
/// Return the path relative to the home folder where we expect to find the
/// .minecraft directory.
pub fn minecraft_dir_relative() -> &'static str {
#[cfg(target_os = "windows")]
{
".minecraft"
}
#[cfg(target_os = "macos")]
{
"Library/Application Support/minecraft"
}
#[cfg(target_os = "linux")]
{
".minecraft"
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
".minecraft"
}
}

View file

@ -14,7 +14,7 @@ pub mod ping;
mod player;
pub use account::Account;
pub use client::{Client, ClientInformation, Event};
pub use client::{ChatPacket, Client, ClientInformation, Event, JoinError};
pub use movement::MoveDirection;
pub use player::Player;

View file

@ -3,12 +3,13 @@ description = "Miscellaneous things in Azalea."
edition = "2021"
license = "MIT"
name = "azalea-core"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-core"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = {path = "../azalea-buf", version = "^0.2.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.2.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.2.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.3.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.3.0" }
uuid = "^1.1.2"

View file

@ -20,7 +20,7 @@ pub enum Err {
impl Debug for Err {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match self {
Err::InvalidDifficulty(s) => write!(f, "Invalid difficulty: {}", s),
Err::InvalidDifficulty(s) => write!(f, "Invalid difficulty: {s}"),
}
}
}
@ -52,7 +52,7 @@ impl Difficulty {
2 => Difficulty::NORMAL,
3 => Difficulty::HARD,
// this shouldn't be possible because of the modulo, so panicking is fine
_ => panic!("Unknown difficulty id: {}", id),
_ => panic!("Unknown difficulty id: {id}"),
}
}

View file

@ -42,7 +42,7 @@ impl Axis {
0 => Axis::X,
1 => Axis::Y,
2 => Axis::Z,
_ => panic!("Invalid ordinal {}", ordinal),
_ => panic!("Invalid ordinal {ordinal}"),
}
}
}

View file

@ -73,7 +73,7 @@ impl GameType {
"creative" => GameType::CREATIVE,
"adventure" => GameType::ADVENTURE,
"spectator" => GameType::SPECTATOR,
_ => panic!("Unknown game type name: {}", name),
_ => panic!("Unknown game type name: {name}"),
}
}
}

View file

@ -3,13 +3,14 @@ description = "Cryptography features used in Minecraft."
edition = "2021"
license = "MIT"
name = "azalea-crypto"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-crypto"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
aes = "0.8.1"
azalea-buf = {path = "../azalea-buf", version = "^0.2.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
cfb8 = "0.8.1"
num-bigint = "^0.4.3"
rand = {version = "^0.8.4", features = ["getrandom"]}

View file

@ -3,7 +3,8 @@ description = "Translate Minecraft strings from their id."
edition = "2021"
license = "MIT"
name = "azalea-language"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-language"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -3,13 +3,14 @@ description = "A fast NBT serializer and deserializer."
edition = "2021"
license = "MIT"
name = "azalea-nbt"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-nbt"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ahash = "^0.8.0"
azalea-buf = {path = "../azalea-buf", version = "^0.2.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
byteorder = "^1.4.3"
flate2 = "^1.0.23"
num-derive = "^0.3.3"

View file

@ -10,10 +10,10 @@ pub enum Error {
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Error::InvalidTagType(id) => write!(f, "Invalid tag type: {}", id),
Error::InvalidTagType(id) => write!(f, "Invalid tag type: {id}"),
Error::InvalidTag => write!(f, "Invalid tag"),
Error::WriteError(e) => write!(f, "Write error: {}", e),
Error::Utf8Error(e) => write!(f, "Utf8 error: {}", e),
Error::WriteError(e) => write!(f, "Write error: {e}"),
Error::Utf8Error(e) => write!(f, "Utf8 error: {e}"),
Error::UnexpectedEof => write!(f, "Unexpected EOF"),
}
}

View file

@ -3,14 +3,15 @@ description = "Physics for Minecraft entities."
edition = "2021"
license = "MIT"
name = "azalea-physics"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-physics"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-block = { path = "../azalea-block", version = "^0.2.0" }
azalea-core = { path = "../azalea-core", version = "^0.2.0" }
azalea-world = { path = "../azalea-world", version = "^0.2.0" }
azalea-block = { path = "../azalea-block", version = "^0.3.0" }
azalea-core = { path = "../azalea-core", version = "^0.3.0" }
azalea-world = { path = "../azalea-world", version = "^0.3.0" }
lazy_static = "1.4.0"
[dev-dependencies]

File diff suppressed because it is too large Load diff

View file

@ -95,7 +95,9 @@ impl<'a> Iterator for BlockCollisions<'a> {
let chunk_lock = chunk.lock().unwrap();
let pos = item.pos;
let block_state: BlockState = chunk_lock.get(&(&pos).into(), self.dimension.min_y());
let block_state: BlockState = chunk_lock
.get(&(&pos).into(), self.dimension.min_y())
.unwrap_or(BlockState::Air);
// TODO: continue if self.only_suffocating_blocks and the block is not suffocating

View file

@ -19,7 +19,7 @@ pub fn box_shape(
max_y: f64,
max_z: f64,
) -> VoxelShape {
assert!(min_x >= 0., "min_x must be >= 0 but was {}", min_x);
assert!(min_x >= 0., "min_x must be >= 0 but was {min_x}");
assert!(min_y >= 0.);
assert!(min_z >= 0.);
assert!(max_x >= 0.);

View file

@ -3,24 +3,25 @@ description = "Send and receive Minecraft packets."
edition = "2021"
license = "MIT"
name = "azalea-protocol"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-protocol"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
async-compression = {version = "^0.3.8", features = ["tokio", "zlib"], optional = true}
async-recursion = "1.0.0"
azalea-auth = {path = "../azalea-auth", version = "^0.2.1" }
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.2.0" }
azalea-brigadier = {path = "../azalea-brigadier", version = "^0.2.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.2.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.2.0" }
azalea-core = {path = "../azalea-core", optional = true, version = "^0.2.0" }
azalea-crypto = {path = "../azalea-crypto", version = "^0.2.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.2.0" }
azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.2.0" }
azalea-registry = {path = "../azalea-registry", version = "^0.2.0" }
azalea-world = {path = "../azalea-world", version = "^0.2.0" }
azalea-auth = {path = "../azalea-auth", version = "^0.3.0" }
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.3.0" }
azalea-brigadier = {path = "../azalea-brigadier", version = "^0.3.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.3.0" }
azalea-core = {path = "../azalea-core", optional = true, version = "^0.3.0" }
azalea-crypto = {path = "../azalea-crypto", version = "^0.3.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.3.0" }
azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.3.0" }
azalea-registry = {path = "../azalea-registry", version = "^0.3.0" }
azalea-world = {path = "../azalea-world", version = "^0.3.0" }
byteorder = "^1.4.3"
bytes = "^1.1.0"
flate2 = "1.0.23"

View file

@ -3,7 +3,8 @@ description = "Macros internally used in azalea-protocol."
edition = "2021"
license = "MIT"
name = "azalea-protocol-macros"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-protocol/azalea-protocol-macros"
[lib]
proc-macro = true

View file

@ -55,26 +55,24 @@ pub struct WriteConnection<W: ProtocolPacket> {
/// hostname: address.host.to_string(),
/// port: address.port,
/// intention: ConnectionProtocol::Login,
/// }
/// .get(),
/// )
/// .await?;
/// let mut conn = conn.login();
/// }.get());
///
/// // login
/// conn.write(
/// ServerboundHelloPacket {
/// username,
/// public_key: None,
/// profile_id: None,
/// }
/// .get(),
/// )
/// .await?;
/// .await?;
/// let mut conn = conn.login();
///
/// let (conn, game_profile) = loop {
/// let packet_result = conn.read().await;
/// match packet_result {
/// // login
/// conn.write(
/// ServerboundHelloPacket {
/// username,
/// public_key: None,
/// profile_id: None,
/// }
/// .get(),
/// )
/// .await?;
///
/// let (conn, game_profile) = loop {
/// let packet_result = conn.read().await?;
/// Ok(packet) => match packet {
/// ClientboundLoginPacket::Hello(p) => {
/// let e = azalea_crypto::encrypt(&p.public_key, &p.nonce).unwrap();
@ -87,7 +85,8 @@ pub struct WriteConnection<W: ProtocolPacket> {
/// .get(),
/// )
/// .await?;
/// conn.set_encryption_key(e.secret_key); }
/// conn.set_encryption_key(e.secret_key);
/// }
/// ClientboundLoginPacket::LoginCompression(p) => {
/// conn.set_compression_threshold(p.compression_threshold);
/// }

View file

@ -3,6 +3,9 @@
//! You should probably use [`azalea`] or [`azalea_client`] instead, as
//! azalea_protocol delegates much of the work, such as auth, to the user of
//! the crate.
//!
//! [`azalea`]: https://crates.io/crates/azalea
//! [`azalea_client`]: https://crates.io/crates/azalea-client
// these two are necessary for thiserror backtraces
#![feature(error_generic_member_access)]

View file

@ -1,7 +1,7 @@
use azalea_buf::{
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
};
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::Cursor;
use std::io::Write;

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -2,7 +2,6 @@ use azalea_buf::McBuf;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundUpdateViewDistancePacket {
#[var]
pub view_distance: i32,
pub struct ClientboundContainerClosePacket {
pub container_id: u8,
}

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -1,11 +0,0 @@
use azalea_buf::McBuf;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundEntityVelocityPacket {
#[var]
pub entity_id: u32,
pub x_vel: i16,
pub y_vel: i16,
pub z_vel: i16,
}

View file

@ -1,6 +1,6 @@
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::{Cursor, Write};

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -2,8 +2,8 @@ use azalea_buf::{
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
};
use azalea_chat::{
component::Component,
translatable_component::{StringOrComponent, TranslatableComponent},
Component,
};
use azalea_core::BitSet;
use azalea_crypto::MessageSignature;

View file

@ -1,6 +1,7 @@
use azalea_buf::McBuf;
use azalea_protocol_macros::ClientboundGamePacket;
/// Unused in vanilla.
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPlayerCombatEndPacket {
#[var]

View file

@ -1,5 +1,6 @@
use azalea_buf::McBuf;
use azalea_protocol_macros::ClientboundGamePacket;
/// Unused in vanilla.
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPlayerCombatEnterPacket {}

View file

@ -1,7 +1,8 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
/// Used to send a respawn screen.
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPlayerCombatKillPacket {
#[var]

View file

@ -1,7 +1,7 @@
use crate::packets::login::serverbound_hello_packet::ProfilePublicKeyData;
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable};
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::{Cursor, Write};
use uuid::Uuid;

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -1,5 +1,5 @@
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::{Cursor, Write};

View file

@ -1,5 +1,5 @@
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
use azalea_chat::{component::Component, style::ChatFormatting};
use azalea_chat::{style::ChatFormatting, Component};
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::{Cursor, Write};

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_core::{ResourceLocation, Slot};
use azalea_protocol_macros::ClientboundGamePacket;
use std::collections::HashMap;

View file

@ -12,6 +12,7 @@ pub mod clientbound_boss_event_packet;
pub mod clientbound_change_difficulty_packet;
pub mod clientbound_command_suggestions_packet;
pub mod clientbound_commands_packet;
pub mod clientbound_container_close_packet;
pub mod clientbound_container_set_content_packet;
pub mod clientbound_container_set_data_packet;
pub mod clientbound_container_set_slot_packet;
@ -21,7 +22,6 @@ pub mod clientbound_custom_payload_packet;
pub mod clientbound_custom_sound_packet;
pub mod clientbound_delete_chat_packet;
pub mod clientbound_disconnect_packet;
pub mod clientbound_disguised_chat_packet;
pub mod clientbound_entity_event_packet;
pub mod clientbound_explode_packet;
pub mod clientbound_forget_level_chunk_packet;
@ -50,8 +50,6 @@ pub mod clientbound_player_chat_packet;
pub mod clientbound_player_combat_end_packet;
pub mod clientbound_player_combat_enter_packet;
pub mod clientbound_player_combat_kill_packet;
pub mod clientbound_player_info_remove_packet;
pub mod clientbound_player_info_update_packet;
pub mod clientbound_player_look_at_packet;
pub mod clientbound_player_position_packet;
pub mod clientbound_recipe_packet;
@ -100,7 +98,6 @@ pub mod clientbound_take_item_entity_packet;
pub mod clientbound_teleport_entity_packet;
pub mod clientbound_update_advancements_packet;
pub mod clientbound_update_attributes_packet;
pub mod clientbound_update_enabled_features_packet;
pub mod clientbound_update_mob_effect_packet;
pub mod clientbound_update_recipes_packet;
pub mod clientbound_update_tags_packet;
@ -235,7 +232,6 @@ declare_state_packets!(
0x16: clientbound_custom_sound_packet::ClientboundCustomSoundPacket,
0x17: clientbound_delete_chat_packet::ClientboundDeleteChatPacket,
0x18: clientbound_disconnect_packet::ClientboundDisconnectPacket,
0x19: clientbound_disguised_chat_packet::ClientboundDisguisedChatPacket,
0x1a: clientbound_entity_event_packet::ClientboundEntityEventPacket,
0x1b: clientbound_explode_packet::ClientboundExplodePacket,
0x1c: clientbound_forget_level_chunk_packet::ClientboundForgetLevelChunkPacket,
@ -264,8 +260,6 @@ declare_state_packets!(
0x33: clientbound_player_combat_end_packet::ClientboundPlayerCombatEndPacket,
0x34: clientbound_player_combat_enter_packet::ClientboundPlayerCombatEnterPacket,
0x35: clientbound_player_combat_kill_packet::ClientboundPlayerCombatKillPacket,
0x36: clientbound_player_info_remove_packet::ClientboundPlayerInfoRemovePacket,
0x37: clientbound_player_info_update_packet::ClientboundPlayerInfoUpdatePacket,
0x38: clientbound_player_look_at_packet::ClientboundPlayerLookAtPacket,
0x39: clientbound_player_position_packet::ClientboundPlayerPositionPacket,
0x3a: clientbound_recipe_packet::ClientboundRecipePacket,
@ -314,7 +308,6 @@ declare_state_packets!(
0x65: clientbound_teleport_entity_packet::ClientboundTeleportEntityPacket,
0x66: clientbound_update_advancements_packet::ClientboundUpdateAdvancementsPacket,
0x67: clientbound_update_attributes_packet::ClientboundUpdateAttributesPacket,
0x68: clientbound_update_enabled_features_packet::ClientboundUpdateEnabledFeaturesPacket,
0x69: clientbound_update_mob_effect_packet::ClientboundUpdateMobEffectPacket,
0x6a: clientbound_update_recipes_packet::ClientboundUpdateRecipesPacket,
0x6b: clientbound_update_tags_packet::ClientboundUpdateTagsPacket,

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundLoginPacket;
#[derive(Clone, Debug, McBuf, ClientboundLoginPacket)]

View file

@ -1,5 +1,5 @@
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundStatusPacket;
use serde::Deserialize;
use serde_json::Value;

View file

@ -35,7 +35,7 @@ fn packet_encoder<P: ProtocolPacket + std::fmt::Debug>(
return Err(PacketEncodeError::TooBig {
actual: buf.len(),
maximum: MAXIMUM_UNCOMPRESSED_LENGTH as usize,
packet_string: format!("{:?}", packet),
packet_string: format!("{packet:?}"),
});
}
Ok(buf)

View file

@ -3,10 +3,11 @@ description = "Use Minecraft's registries."
edition = "2021"
license = "MIT"
name = "azalea-registry"
version = "0.2.0"
version = "0.3.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-registry"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = {path = "../azalea-buf", version = "^0.2.0" }
azalea-registry-macros = {path = "./azalea-registry-macros", version = "^0.2.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-registry-macros = {path = "./azalea-registry-macros", version = "^0.3.0" }

View file

@ -3,7 +3,8 @@ description = "Macros internally used in azalea-registry."
edition = "2021"
license = "MIT"
name = "azalea-registry-macros"
version = "0.2.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-registry/azalea-registry-macros"
version = "0.3.0"
[lib]
proc-macro = true

View file

@ -76,8 +76,8 @@ pub fn registry(input: TokenStream) -> TokenStream {
let max_id = input.items.len() as u32;
let doc_0 = format!("Transmutes a u32 to a {}.", name);
let doc_1 = format!("The `id` should be at most {}.", max_id);
let doc_0 = format!("Transmutes a u32 to a {name}.");
let doc_1 = format!("The `id` should be at most {max_id}.");
generated.extend(quote! {
impl #name {
@ -97,7 +97,7 @@ pub fn registry(input: TokenStream) -> TokenStream {
}
});
let doc_0 = format!("Safely transmutes a u32 to a {}.", name);
let doc_0 = format!("Safely transmutes a u32 to a {name}.");
generated.extend(quote! {
impl TryFrom<u32> for #name {

View file

@ -3,17 +3,18 @@ description = "The Minecraft world representation used in Azalea."
edition = "2021"
license = "MIT"
name = "azalea-world"
version = "0.2.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-world"
version = "0.3.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.2.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.2.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.2.0" }
azalea-core = {path = "../azalea-core", version = "^0.2.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.2.0" }
azalea-registry = {path = "../azalea-registry", version = "^0.2.0" }
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.3.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.3.0" }
azalea-core = {path = "../azalea-core", version = "^0.3.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.3.0" }
azalea-registry = {path = "../azalea-registry", version = "^0.3.0" }
log = "0.4.17"
nohash-hasher = "0.2.0"
thiserror = "1.0.34"

View file

@ -79,23 +79,21 @@ impl ChunkStorage {
&& (chunk_pos.z - self.view_center.z).unsigned_abs() <= self.chunk_radius
}
pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option<BlockState> {
pub fn get_block_state(&self, pos: &BlockPos) -> Option<BlockState> {
let chunk_pos = ChunkPos::from(pos);
let chunk = self[&chunk_pos].as_ref()?;
let chunk = chunk.lock().unwrap();
Some(chunk.get(&ChunkBlockPos::from(pos), min_y))
chunk.get(&ChunkBlockPos::from(pos), self.min_y)
}
pub fn set_block_state(
&self,
pos: &BlockPos,
state: BlockState,
min_y: i32,
) -> Option<BlockState> {
pub fn set_block_state(&self, pos: &BlockPos, state: BlockState) -> Option<BlockState> {
if pos.y < self.min_y || pos.y >= (self.min_y + self.height as i32) {
return None;
}
let chunk_pos = ChunkPos::from(pos);
let chunk = self[&chunk_pos].as_ref()?;
let mut chunk = chunk.lock().unwrap();
Some(chunk.get_and_set(&ChunkBlockPos::from(pos), state, min_y))
Some(chunk.get_and_set(&ChunkBlockPos::from(pos), state, self.min_y))
}
pub fn replace_with_packet_data(
@ -160,17 +158,21 @@ impl Chunk {
}
pub fn section_index(&self, y: i32, min_y: i32) -> u32 {
assert!(y >= min_y, "y ({}) must be at least {}", y, min_y);
assert!(y >= min_y, "y ({y}) must be at least {min_y}");
let min_section_index = min_y.div_floor(16);
(y.div_floor(16) - min_section_index) as u32
}
pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> BlockState {
let section_index = self.section_index(pos.y, min_y);
pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> Option<BlockState> {
let section_index = self.section_index(pos.y, min_y) as usize;
if section_index >= self.sections.len() {
// y position is out of bounds
return None;
};
// TODO: make sure the section exists
let section = &self.sections[section_index as usize];
let section = &self.sections[section_index];
let chunk_section_pos = ChunkSectionBlockPos::from(pos);
section.get(chunk_section_pos)
Some(section.get(chunk_section_pos))
}
pub fn get_and_set(
@ -304,4 +306,25 @@ mod tests {
assert_eq!(chunk.section_index(-48, -64), 1);
assert_eq!(chunk.section_index(128, -64), 12);
}
#[test]
fn test_out_of_bounds_y() {
let mut chunk_storage = ChunkStorage::default();
chunk_storage[&ChunkPos { x: 0, z: 0 }] = Some(Arc::new(Mutex::new(Chunk::default())));
assert!(chunk_storage
.get_block_state(&BlockPos { x: 0, y: 319, z: 0 })
.is_some());
assert!(chunk_storage
.get_block_state(&BlockPos { x: 0, y: 320, z: 0 })
.is_none());
assert!(chunk_storage
.get_block_state(&BlockPos { x: 0, y: 338, z: 0 })
.is_none());
assert!(chunk_storage
.get_block_state(&BlockPos { x: 0, y: -64, z: 0 })
.is_some());
assert!(chunk_storage
.get_block_state(&BlockPos { x: 0, y: -65, z: 0 })
.is_none());
}
}

View file

@ -1,6 +1,6 @@
use azalea_buf::{BufReadError, McBufVarReadable};
use azalea_buf::{McBuf, McBufReadable, McBufWritable};
use azalea_chat::component::Component;
use azalea_chat::Component;
use azalea_core::{BlockPos, Direction, GlobalPos, Particle, Slot};
use std::io::{Cursor, Write};
use uuid::Uuid;

View file

@ -62,11 +62,11 @@ impl Dimension {
}
pub fn get_block_state(&self, pos: &BlockPos) -> Option<BlockState> {
self.chunk_storage.get_block_state(pos, self.min_y())
self.chunk_storage.get_block_state(pos)
}
pub fn set_block_state(&mut self, pos: &BlockPos, state: BlockState) -> Option<BlockState> {
self.chunk_storage.set_block_state(pos, state, self.min_y())
self.chunk_storage.set_block_state(pos, state)
}
pub fn set_entity_pos(&mut self, entity_id: u32, new_pos: Vec3) -> Result<(), MoveEntityError> {

View file

@ -3,15 +3,16 @@ description = "A framework for creating Minecraft bots."
edition = "2021"
license = "MIT"
name = "azalea"
version = "0.2.4"
repository = "https://github.com/mat-1/azalea/tree/main/azalea"
version = "0.3.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "^1.0.65"
async-trait = "^0.1.57"
azalea-client = { version = "0.2.2", path = "../azalea-client" }
azalea-protocol = { version = "0.2.0", path = "../azalea-protocol" }
azalea-client = {version = "0.3.0", path = "../azalea-client"}
azalea-protocol = {version = "0.3.0", path = "../azalea-protocol"}
parking_lot = "^0.12.1"
thiserror = "^1.0.37"
tokio = "^1.21.1"

View file

@ -94,8 +94,10 @@ where
/// The address of the server that we're connecting to. This can be a
/// `&str`, [`ServerAddress`], or anything that implements
/// `TryInto<ServerAddress>`.
///
/// [`ServerAddress`]: azalea_protocol::ServerAddress
pub address: A,
/// The account that's going to join the server,
/// The account that's going to join the server.
pub account: Account,
/// A list of plugins that are going to be used. Plugins are external
/// crates that add extra functionality to Azalea.
@ -116,6 +118,17 @@ where
/// ```
pub state: S,
/// The function that's called whenever we get an event.
///
/// # Examples
///
/// ```rust
/// use anyhow::Result;
/// use azalea::prelude::*;
///
/// async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
/// Ok(())
/// }
/// ```
pub handle: HandleFn<Fut, S>,
}
@ -123,6 +136,8 @@ where
pub enum Error {
#[error("Invalid address")]
InvalidAddress,
#[error("Join error: {0}")]
Join(#[from] azalea_client::JoinError),
}
/// Join a server and start handling events. This function will run forever until
@ -151,7 +166,7 @@ pub async fn start<
Err(_) => return Err(Error::InvalidAddress),
};
let (bot, mut rx) = Client::join(&options.account, address).await.unwrap();
let (bot, mut rx) = Client::join(&options.account, address).await?;
let state = options.state;
let bot_plugin = bot::Plugin::default();

View file

@ -121,6 +121,9 @@ def generate_packet(burger_packets, mappings: Mappings, target_packet_id, target
def set_packets(packet_ids: list[int], packet_class_names: list[str], direction: str, state: str):
assert len(packet_ids) == len(packet_class_names)
# ids are repeated
assert len(packet_ids) == len(set(packet_ids))
# sort the packets by id
packet_ids, packet_class_names = [list(x) for x in zip(
*sorted(zip(packet_ids, packet_class_names), key=lambda pair: pair[0]))] # type: ignore
@ -377,6 +380,8 @@ def change_packet_ids(id_map: dict[int, int], direction: str, state: str):
for packet_id in existing_packet_ids:
new_packet_id = id_map.get(packet_id, packet_id)
if new_packet_id in new_packet_ids:
raise Exception('Two packets have the same id')
new_packet_ids.append(new_packet_id)
set_packets(new_packet_ids, existing_packet_class_names, direction, state)

View file

@ -8,11 +8,43 @@ COLLISION_BLOCKS_RS_DIR = get_dir_location(
def generate_block_shapes(blocks: dict, shapes: dict, block_states_report, block_datas_burger, mappings: Mappings):
code = generate_block_shapes_code(blocks, shapes, block_states_report, block_datas_burger, mappings)
blocks, shapes = simplify_shapes(blocks, shapes)
code = generate_block_shapes_code(
blocks, shapes, block_states_report, block_datas_burger, mappings)
with open(COLLISION_BLOCKS_RS_DIR, 'w') as f:
f.write(code)
def simplify_shapes(blocks: dict, shapes: dict):
shape_to_new_id = {}
new_id_increment = 0
new_shapes = {}
old_id_to_new_id = {}
for shape_id, shape in sorted(shapes.items(), key=lambda shape: int(shape[0])):
# tuples are hashable
shape_as_tuple = tuple(map(tuple, shape))
if shape_as_tuple not in shape_to_new_id:
shape_to_new_id[shape_as_tuple] = new_id_increment
old_id_to_new_id[shape_id] = new_id_increment
new_shapes[new_id_increment] = shape
new_id_increment += 1
else:
old_id_to_new_id[shape_id] = shape_to_new_id[shape_as_tuple]
# now map the blocks to the new shape ids
for block_id, shape_ids in blocks.items():
if isinstance(shape_ids, int):
blocks[block_id] = old_id_to_new_id[str(shape_ids)]
else:
blocks[block_id] = [old_id_to_new_id[str(shape_id)]
for shape_id in shape_ids]
return blocks, new_shapes
def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report, block_datas_burger, mappings: Mappings):
# look at downloads/generator-mod-*/blockCollisionShapes.json for format of blocks and shapes
@ -39,7 +71,7 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report,
variant_values = []
for value in tuple(possible_state.get('properties', {}).values()):
variant_values.append(to_camel_case(value))
if variant_values == []:
variant_name = to_camel_case(block_id)
else:
@ -47,13 +79,13 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report,
if shape_id not in shape_ids_to_variants:
shape_ids_to_variants[shape_id] = []
shape_ids_to_variants[shape_id].append(f'BlockState::{variant_name}')
shape_ids_to_variants[shape_id].append(
f'BlockState::{variant_name}')
# shape 1 is the most common so we have a _ => &SHAPE1 at the end
del shape_ids_to_variants[1]
for shape_id, variants in shape_ids_to_variants.items():
generated_match_inner_code += f'{"|".join(variants)} => &SHAPE{shape_id},\n'
return f'''
//! Autogenerated block collisions for every block
@ -67,7 +99,7 @@ use crate::collision::{{self, Shapes}};
use azalea_block::*;
use lazy_static::lazy_static;
trait BlockWithShape {{
pub trait BlockWithShape {{
fn shape(&self) -> &'static VoxelShape;
}}
@ -106,5 +138,3 @@ def generate_code_for_shape(shape_id: str, parts: list[list[float]]):
code += f' {steps[-1]}\n'
code += '};\n'
return code

View file

@ -45,7 +45,7 @@ def burger_type_to_rust_type(burger_type, field_name: Optional[str] = None, inst
elif burger_type == 'chatcomponent':
field_type_rs = 'Component'
uses.add('azalea_chat::component::Component')
uses.add('azalea_chat::Component')
elif burger_type == 'identifier':
field_type_rs = 'ResourceLocation'
uses.add('azalea_core::ResourceLocation')
@ -164,6 +164,5 @@ def clean_property_name(property_name):
# `type` is a reserved keyword, so we use kind instead ¯\_(ツ)_/¯
if property_name == 'type':
property_name = 'kind'
return property_name
return property_name