Skip to main content

ghast_client/
lib.rs

1//! Headless Minecraft Java Edition client for the ghast library.
2//!
3//! - [`Client`]: connect (directly or through a SOCKS5 proxy, see [`ghast_auth::connect`]),
4//!   handshake, login (offline; online mode with the `microsoft` feature), compression and
5//!   encryption, then the play state: keep-alives, teleports, window confirms, health,
6//!   respawn, chat.
7//! - A fixed 50 ms tick loop with vanilla 1.8.9's tick order (see [`engine`](crate::TickContext)
8//!   for the details): inbound packets → [`Behavior::tick`] (actions written immediately) →
9//!   rotation → movement → exactly one movement packet.
10//! - A version-agnostic API: behaviours see [`TickContext`] and the types of [`common`],
11//!   never packets. The connection is generic over the protocol version
12//!   ([`version::ClientVersion`]), so each supported version is monomorphised.
13//! - Packets nobody needs are dropped before they are decoded; a behaviour opts into more
14//!   with [`Behavior::interests`].
15//!
16//! Supported versions: 1.8.9 (protocol 47) and 1.16.5 (protocol 754).
17//!
18//! ```no_run
19//! use ghast_client::{Account, Behavior, Client, GameVersion, Interests, TickContext};
20//!
21//! struct Echo;
22//! impl Behavior for Echo {
23//!     fn interests(&self) -> Interests {
24//!         Interests::CHAT
25//!     }
26//!     fn tick(&mut self, ctx: &mut TickContext<'_>) {
27//!         let lines: Vec<String> = ctx.events().chat.iter().map(|m| m.plain()).collect();
28//!         for line in lines {
29//!             println!("chat: {line}");
30//!         }
31//!         if ctx.is_dead() {
32//!             ctx.respawn();
33//!         }
34//!     }
35//! }
36//!
37//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
38//! let client = Client::new("localhost:25565".parse()?, GameVersion::V1_8_9, Account::offline("Steve")?);
39//! let end = client.run(&mut Echo).await?;
40//! println!("session ended: {end:?}");
41//! # Ok(())
42//! # }
43//! ```
44
45#![forbid(unsafe_code)]
46#![warn(missing_docs, rust_2018_idioms, unreachable_pub)]
47
48mod client;
49pub mod common;
50mod engine;
51mod error;
52pub mod hands;
53mod interest;
54pub mod movement;
55mod record;
56pub mod rotation;
57mod sim;
58#[cfg(test)]
59mod trace_replay;
60pub mod version;
61
62pub use client::{Account, Client, TICK};
63pub use common::{ChatMessage, ClientSettings, Controls, Face, GameMode, Health, Pose, Vec3};
64pub use engine::{Behavior, ClickRefused, ClickTicket, Idle, RawInbound, TickContext, TickEvents};
65pub use error::{ClientError, SessionEnd};
66pub use ghast_entity as entity;
67pub use ghast_inventory as inventory;
68pub use ghast_protocol::BlockPos;
69pub use ghast_world as world;
70pub use hands::{BlockHit, Buttons};
71pub use interest::Interests;
72pub use sim::{ForceStepPosition, WorldView};
73pub use version::GameVersion;
74
75/// Re-exports of the connection setup types from `ghast-auth`.
76pub mod connect {
77    pub use ghast_auth::connect::{
78        ConnectError, Connector, ProxyPolicy, Route, TargetAddr, Timeouts,
79    };
80    pub use ghast_auth::socks5::Socks5Proxy;
81}