aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-10-23 19:00:24 -0500
committerGitHub <noreply@github.com>2022-10-23 19:00:24 -0500
commit65da123631b0a2dc078786f60fa6b213e8b430ee (patch)
tree8854f29c4240d36bec1710ebc2293a488c495d3d
parent587001724acf8a7c6de30927da31c1f5fd7fdb09 (diff)
downloadazalea-drasl-65da123631b0a2dc078786f60fa6b213e8b430ee.tar.xz
Add Client::set_client_information (#33)
* start adding options * add default options * send options packet by default * mention set_options in Client::join doc * make TranslatableComponent::read return TextComponent * change set_options to set_client_information * clean up some code * Add `Initialize` event * fix some clippy warnings * change `Client::options` to `client_information`
-rw-r--r--azalea-auth/src/auth.rs6
-rw-r--r--azalea-buf/src/write.rs1
-rw-r--r--[-rwxr-xr-x]azalea-chat/src/text_component.rs0
-rw-r--r--[-rwxr-xr-x]azalea-chat/src/translatable_component.rs6
-rw-r--r--azalea-client/src/chat.rs4
-rw-r--r--azalea-client/src/client.rs51
-rwxr-xr-xazalea-client/src/lib.rs2
-rw-r--r--azalea-protocol/src/connect.rs2
-rw-r--r--azalea-protocol/src/packets/game/serverbound_client_information_packet.rs28
-rw-r--r--azalea-world/src/chunk_storage.rs3
-rw-r--r--azalea/examples/craft_dig_straight_down.rs4
-rw-r--r--azalea/examples/echo.rs4
-rw-r--r--azalea/examples/potatobot/main.rs2
-rw-r--r--azalea/src/lib.rs2
-rw-r--r--azalea/src/prelude.rs2
-rw-r--r--bot/src/main.rs3
16 files changed, 97 insertions, 23 deletions
diff --git a/azalea-auth/src/auth.rs b/azalea-auth/src/auth.rs
index 3e5f82d8..0d7c7ace 100644
--- a/azalea-auth/src/auth.rs
+++ b/azalea-auth/src/auth.rs
@@ -56,11 +56,7 @@ pub enum AuthError {
/// though, and in case the Microsoft API does start providing the real email.
pub async fn auth(email: &str, opts: AuthOpts) -> Result<AuthResult, AuthError> {
let cached_account = if let Some(cache_file) = &opts.cache_file {
- if let Some(account) = cache::get_account_in_cache(cache_file, email).await {
- Some(account)
- } else {
- None
- }
+ cache::get_account_in_cache(cache_file, email).await
} else {
None
};
diff --git a/azalea-buf/src/write.rs b/azalea-buf/src/write.rs
index e1f1ffb1..e00ddce9 100644
--- a/azalea-buf/src/write.rs
+++ b/azalea-buf/src/write.rs
@@ -110,7 +110,6 @@ impl McBufWritable for String {
}
}
-
impl McBufWritable for &str {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
write_utf_with_len(buf, self, MAX_STRING_LENGTH.into())
diff --git a/azalea-chat/src/text_component.rs b/azalea-chat/src/text_component.rs
index 96eef08e..96eef08e 100755..100644
--- a/azalea-chat/src/text_component.rs
+++ b/azalea-chat/src/text_component.rs
diff --git a/azalea-chat/src/translatable_component.rs b/azalea-chat/src/translatable_component.rs
index 750f65c4..918c2c42 100755..100644
--- a/azalea-chat/src/translatable_component.rs
+++ b/azalea-chat/src/translatable_component.rs
@@ -59,7 +59,7 @@ impl TranslatableComponent {
.args
.get(matched)
.cloned()
- .unwrap_or(StringOrComponent::String("".to_string()));
+ .unwrap_or_else(|| StringOrComponent::String("".to_string()));
components.push(TextComponent::new(built_text.clone()));
built_text.clear();
@@ -107,7 +107,7 @@ impl TranslatableComponent {
Ok(TextComponent {
base: BaseComponent {
- siblings: components.into_iter().map(|c| Component::Text(c)).collect(),
+ siblings: components.into_iter().map(Component::Text).collect(),
style: Style::default(),
},
text: "".to_string(),
@@ -135,7 +135,7 @@ 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.to_string()),
+ StringOrComponent::Component(c) => write!(f, "{}", c),
}
}
}
diff --git a/azalea-client/src/chat.rs b/azalea-client/src/chat.rs
index 335261e6..18fa4549 100644
--- a/azalea-client/src/chat.rs
+++ b/azalea-client/src/chat.rs
@@ -84,8 +84,8 @@ impl Client {
/// # }
/// ```
pub async fn chat(&self, message: &str) -> Result<(), std::io::Error> {
- if message.starts_with('/') {
- self.send_command_packet(&message[1..]).await
+ if let Some(command) = message.strip_prefix('/') {
+ self.send_command_packet(command).await
} else {
self.send_chat_packet(message).await
}
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs
index af47b2cd..60f9c9fc 100644
--- a/azalea-client/src/client.rs
+++ b/azalea-client/src/client.rs
@@ -9,6 +9,7 @@ use azalea_protocol::{
clientbound_player_chat_packet::ClientboundPlayerChatPacket,
clientbound_system_chat_packet::ClientboundSystemChatPacket,
serverbound_accept_teleportation_packet::ServerboundAcceptTeleportationPacket,
+ serverbound_client_information_packet::ServerboundClientInformationPacket,
serverbound_custom_payload_packet::ServerboundCustomPayloadPacket,
serverbound_keep_alive_packet::ServerboundKeepAlivePacket,
serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPosRotPacket,
@@ -30,7 +31,7 @@ use azalea_world::{
Dimension,
};
use log::{debug, error, warn};
-use parking_lot::Mutex;
+use parking_lot::{Mutex, RwLock};
use std::{
fmt::Debug,
io::{self, Cursor},
@@ -43,10 +44,17 @@ use tokio::{
time::{self},
};
+pub type ClientInformation = ServerboundClientInformationPacket;
+
/// Events are sent before they're processed, so for example game ticks happen
/// at the beginning of a tick before anything has happened.
#[derive(Debug, Clone)]
pub enum Event {
+ /// Happens right after the bot switches into the Game state, but before
+ /// it's actually spawned. This can be useful for setting the client
+ /// information with `Client::set_client_information`, so the packet
+ /// doesn't have to be sent twice.
+ Initialize,
Login,
Chat(ChatPacket),
/// Happens 20 times per second, but only when the world is loaded.
@@ -78,6 +86,7 @@ pub struct Client {
pub player: Arc<Mutex<Player>>,
pub dimension: Arc<Mutex<Dimension>>,
pub physics_state: Arc<Mutex<PhysicsState>>,
+ pub client_information: Arc<RwLock<ClientInformation>>,
tasks: Arc<Mutex<Vec<JoinHandle<()>>>>,
}
@@ -123,6 +132,8 @@ pub enum HandleError {
impl Client {
/// Connect to a Minecraft server.
///
+ /// To change the render distance and other settings, use [`Client::set_client_information`].
+ ///
/// # Examples
///
/// ```rust,no_run
@@ -240,8 +251,11 @@ impl Client {
dimension: Arc::new(Mutex::new(Dimension::default())),
physics_state: Arc::new(Mutex::new(PhysicsState::default())),
tasks: Arc::new(Mutex::new(Vec::new())),
+ client_information: Arc::new(RwLock::new(ClientInformation::default())),
};
+ tx.send(Event::Initialize).unwrap();
+
// just start up the game loop and we're ready!
// if you get an error right here that means you're doing something with locks wrong
@@ -389,6 +403,12 @@ impl Client {
player_lock.set_entity_id(p.player_id);
}
+ // send the client information that we have set
+ let client_information_packet: ClientInformation =
+ client.client_information.read().clone();
+ client.write_packet(client_information_packet.get()).await?;
+
+ // brand
client
.write_packet(
ServerboundCustomPayloadPacket {
@@ -806,6 +826,35 @@ impl Client {
.entity(entity_id)
.expect("Player entity should be in the given dimension")
}
+
+ /// Returns whether we have a received the login packet yet.
+ pub fn logged_in(&self) -> bool {
+ let dimension = self.dimension.lock();
+ let player = self.player.lock();
+ player.entity(&dimension).is_some()
+ }
+
+ /// Tell the server we changed our game options (i.e. render distance, main hand).
+ /// If this is not set before the login packet, the default will be sent.
+ pub async fn set_client_information(
+ &self,
+ client_information: ServerboundClientInformationPacket,
+ ) -> Result<(), std::io::Error> {
+ {
+ let mut client_information_lock = self.client_information.write();
+ *client_information_lock = client_information;
+ }
+
+ if self.logged_in() {
+ let client_information_packet = {
+ let client_information = self.client_information.read();
+ client_information.clone().get()
+ };
+ self.write_packet(client_information_packet).await?;
+ }
+
+ Ok(())
+ }
}
impl<T> From<std::sync::PoisonError<T>> for HandleError {
diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs
index 61d2d9ee..84af0298 100755
--- a/azalea-client/src/lib.rs
+++ b/azalea-client/src/lib.rs
@@ -14,7 +14,7 @@ pub mod ping;
mod player;
pub use account::Account;
-pub use client::{Client, Event};
+pub use client::{Client, ClientInformation, Event};
pub use movement::MoveDirection;
pub use player::Player;
diff --git a/azalea-protocol/src/connect.rs b/azalea-protocol/src/connect.rs
index 39e34948..da398ff9 100644
--- a/azalea-protocol/src/connect.rs
+++ b/azalea-protocol/src/connect.rs
@@ -166,7 +166,7 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
/// `ClientboundLoginPacket::Hello` packet.
///
/// # Examples
- ///
+ ///
/// ```rust,no_run
/// let token = azalea_auth::auth(azalea_auth::AuthOpts {
/// ..Default::default()
diff --git a/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs b/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs
index 0c1ab14b..61fcbfbe 100644
--- a/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs
@@ -3,20 +3,48 @@ use azalea_protocol_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundClientInformationPacket {
+ /// The locale of the client.
pub language: String,
+ /// The view distance of the client in chunks, same as the render distance
+ /// in-game.
pub view_distance: u8,
+ /// The types of chat messages the client wants to receive. Note that many
+ /// servers ignore this.
pub chat_visibility: ChatVisibility,
+ /// Whether the messages sent from the server should have colors. Note that
+ /// many servers ignore this and always send colored messages.
pub chat_colors: bool,
pub model_customisation: u8,
pub main_hand: HumanoidArm,
pub text_filtering_enabled: bool,
+ /// Whether the client should show up as "Anonymous Player" in the server
+ /// list.
pub allows_listing: bool,
}
+impl Default for ServerboundClientInformationPacket {
+ fn default() -> Self {
+ Self {
+ language: "en_us".to_string(),
+ view_distance: 8,
+ chat_visibility: ChatVisibility::Full,
+ chat_colors: true,
+ model_customisation: 0,
+ main_hand: HumanoidArm::Right,
+ text_filtering_enabled: false,
+ allows_listing: false,
+ }
+ }
+}
+
#[derive(McBuf, Clone, Copy, Debug)]
pub enum ChatVisibility {
+ /// All chat messages should be sent to the client.
Full = 0,
+ /// Chat messages from other players should be not sent to the client, only
+ /// messages from the server like "Player joined the game" should be sent.
System = 1,
+ /// No chat messages should be sent to the client.
Hidden = 2,
}
diff --git a/azalea-world/src/chunk_storage.rs b/azalea-world/src/chunk_storage.rs
index daabb214..0c60376a 100644
--- a/azalea-world/src/chunk_storage.rs
+++ b/azalea-world/src/chunk_storage.rs
@@ -106,7 +106,8 @@ impl ChunkStorage {
if !self.in_range(pos) {
log::trace!(
"Ignoring chunk since it's not in the view range: {}, {}",
- pos.x, pos.z
+ pos.x,
+ pos.z
);
return Ok(());
}
diff --git a/azalea/examples/craft_dig_straight_down.rs b/azalea/examples/craft_dig_straight_down.rs
index 9e675f28..82960a9c 100644
--- a/azalea/examples/craft_dig_straight_down.rs
+++ b/azalea/examples/craft_dig_straight_down.rs
@@ -1,5 +1,5 @@
-use azalea::{pathfinder, Account};
-use azalea::{Bot, Client, Event};
+use azalea::pathfinder;
+use azalea::prelude::*;
use parking_lot::Mutex;
use std::sync::Arc;
diff --git a/azalea/examples/echo.rs b/azalea/examples/echo.rs
index 07dd50c1..8c11d6e7 100644
--- a/azalea/examples/echo.rs
+++ b/azalea/examples/echo.rs
@@ -1,8 +1,6 @@
//! A simple bot that repeats chat messages sent by other players.
-use azalea::{Account, Client, Event};
-use parking_lot::Mutex;
-use std::sync::Arc;
+use azalea::prelude::*;
#[tokio::main]
async fn main() {
diff --git a/azalea/examples/potatobot/main.rs b/azalea/examples/potatobot/main.rs
index 1aa28ecc..54c84570 100644
--- a/azalea/examples/potatobot/main.rs
+++ b/azalea/examples/potatobot/main.rs
@@ -1,7 +1,7 @@
mod autoeat;
use azalea::prelude::*;
-use azalea::{pathfinder, Account, BlockPos, Client, Event, ItemKind, MoveDirection, Plugin, Vec3};
+use azalea::{pathfinder, BlockPos, ItemKind, Vec3};
#[derive(Default, Clone)]
struct State {}
diff --git a/azalea/src/lib.rs b/azalea/src/lib.rs
index 013e2dd3..a7d0791a 100644
--- a/azalea/src/lib.rs
+++ b/azalea/src/lib.rs
@@ -129,7 +129,7 @@ pub enum Error {
/// it gets disconnected from the server.
///
/// # Examples
-///
+///
/// ```rust,no_run
/// let error = azalea::start(azalea::Options {
/// account,
diff --git a/azalea/src/prelude.rs b/azalea/src/prelude.rs
index 0ffb60b8..c09d85e2 100644
--- a/azalea/src/prelude.rs
+++ b/azalea/src/prelude.rs
@@ -1,4 +1,4 @@
-//! The Azalea prelude.
+//! The Azalea prelude. Things that are necessary for a bare-bones bot are re-exported here.
pub use crate::bot::BotTrait;
pub use azalea_client::{Account, Client, Event};
diff --git a/bot/src/main.rs b/bot/src/main.rs
index 9f8bd0c8..e4543b6a 100644
--- a/bot/src/main.rs
+++ b/bot/src/main.rs
@@ -28,6 +28,9 @@ async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()>
Event::Login => {
bot.chat("Hello world").await?;
}
+ Event::Initialize => {
+ println!("initialized");
+ }
Event::Tick => {
bot.jump();
}