McClient

Struct McClient 

Source
pub struct McClient { /* private fields */ }
Expand description

Minecraft server status client.

This client provides methods for querying Minecraft server status with support for both Java Edition and Bedrock Edition servers.

§Features

  • Automatic SRV record lookup for Java servers
  • DNS caching for improved performance
  • Configurable timeouts and concurrency limits
  • Batch queries for multiple servers

§Example

use rust_mc_status::{McClient, ServerEdition};
use std::time::Duration;

let client = McClient::new()
    .with_timeout(Duration::from_secs(5))
    .with_max_parallel(10);

let status = client.ping("mc.hypixel.net", ServerEdition::Java).await?;
println!("Server is online: {}", status.online);

Implementations§

Source§

impl McClient

Source

pub fn new() -> Self

Create a new client with default settings.

Default settings:

  • Timeout: 10 seconds
  • Max parallel: 10 queries
§Example
use rust_mc_status::McClient;

let client = McClient::new();
Source

pub fn with_timeout(self, timeout: Duration) -> Self

Set the request timeout.

This timeout applies to all network operations including DNS resolution, connection establishment, and response reading.

§Arguments
  • timeout - Maximum time to wait for a server response
    • Default: 10 seconds
    • Recommended: 5-10 seconds for most use cases
    • Use shorter timeouts (1-3 seconds) for quick checks
§Returns

Returns Self for method chaining.

§Example
use rust_mc_status::McClient;
use std::time::Duration;

// Quick timeout for fast checks
let fast_client = McClient::new()
    .with_timeout(Duration::from_secs(2));

// Longer timeout for reliable queries
let reliable_client = McClient::new()
    .with_timeout(Duration::from_secs(10));
Source

pub fn with_max_parallel(self, max_parallel: usize) -> Self

Set the maximum number of parallel queries.

This limit controls how many servers can be queried simultaneously when using ping_many. Higher values increase throughput but consume more resources.

§Arguments
  • max_parallel - Maximum number of concurrent server queries
    • Default: 10
    • Recommended: 5-20 for most use cases
    • Higher values (50-100) for batch processing
    • Lower values (1-5) for resource-constrained environments
§Returns

Returns Self for method chaining.

§Performance
  • Higher values = faster batch processing but more memory/CPU usage
  • Lower values = slower but more resource-friendly
  • DNS and SRV caches are shared across all parallel queries
§Example
use rust_mc_status::{McClient, ServerEdition, ServerInfo};

// High concurrency for batch processing
let batch_client = McClient::new()
    .with_max_parallel(50);

// Low concurrency for resource-constrained environments
let limited_client = McClient::new()
    .with_max_parallel(3);
Source

pub fn max_parallel(&self) -> usize

Get the maximum number of parallel queries.

§Example
use rust_mc_status::McClient;

let client = McClient::new().with_max_parallel(20);
assert_eq!(client.max_parallel(), 20);
Source

pub fn timeout(&self) -> Duration

Get the request timeout.

§Example
use rust_mc_status::McClient;
use std::time::Duration;

let client = McClient::new().with_timeout(Duration::from_secs(5));
assert_eq!(client.timeout(), Duration::from_secs(5));
Source

pub fn clear_dns_cache(&self)

Clear DNS cache.

This method clears all cached DNS resolutions. Useful when you need to force fresh DNS lookups or free memory.

§Example
use rust_mc_status::McClient;

let client = McClient::new();
client.clear_dns_cache();
Source

pub fn clear_srv_cache(&self)

Clear SRV record cache.

This method clears all cached SRV record lookups. Useful when you need to force fresh SRV lookups or free memory.

§Example
use rust_mc_status::McClient;

let client = McClient::new();
client.clear_srv_cache();
Source

pub fn clear_all_caches(&self)

Clear all caches (DNS and SRV).

This method clears both DNS and SRV caches. Useful when you need to force fresh lookups or free memory.

§Example
use rust_mc_status::McClient;

let client = McClient::new();
client.clear_all_caches();
Source

pub fn cache_stats(&self) -> CacheStats

Get cache statistics.

Returns the number of entries in DNS and SRV caches.

§Example
use rust_mc_status::McClient;

let client = McClient::new();
let stats = client.cache_stats();
println!("DNS cache entries: {}", stats.dns_entries);
println!("SRV cache entries: {}", stats.srv_entries);
Source

pub async fn resolve_dns_timed( &self, host: &str, port: u16, ) -> Result<(SocketAddr, f64), McError>

Resolve DNS and measure resolution time.

This method resolves a hostname to an IP address and returns both the resolved address and the time taken for resolution. Useful for measuring cache effectiveness and DNS performance.

§Arguments
  • host - Hostname to resolve (e.g., "mc.hypixel.net" or "192.168.1.1")
  • port - Port number (e.g., 25565 for Java, 19132 for Bedrock)
§Returns

Returns Ok((SocketAddr, f64)) where:

  • SocketAddr: Resolved IP address and port
  • f64: Resolution time in milliseconds
§Errors

Returns McError::DnsError if DNS resolution fails.

§Performance Notes
  • First resolution (cold cache): Typically 10-100ms
  • Subsequent resolutions (warm cache): Typically <1ms
  • Cache TTL: 5 minutes
  • Use clear_dns_cache to force fresh lookups
§Example
use rust_mc_status::McClient;

let client = McClient::new();

// First resolution (cold cache - actual DNS lookup)
let (addr1, time1) = client.resolve_dns_timed("mc.hypixel.net", 25565).await?;
println!("First resolution: {:.2} ms", time1);
println!("Resolved to: {}", addr1);

// Second resolution (warm cache - from cache)
let (addr2, time2) = client.resolve_dns_timed("mc.hypixel.net", 25565).await?;
println!("Cached resolution: {:.2} ms", time2);
println!("Cache speedup: {:.1}x faster", time1 / time2);
println!("Time saved: {:.2} ms", time1 - time2);
Source

pub async fn ping( &self, address: &str, edition: ServerEdition, ) -> Result<ServerStatus, McError>

Ping a server and get its status.

This is a convenience method that dispatches to either ping_java or ping_bedrock based on the server edition.

§Arguments
  • address - Server address in one of the following formats:
    • "hostname" - Hostname without port (uses default port for edition)
    • "hostname:port" - Hostname with explicit port
    • "192.168.1.1" - IP address without port (uses default port)
    • "192.168.1.1:25565" - IP address with explicit port
  • edition - Server edition: ServerEdition::Java or ServerEdition::Bedrock
§Returns

Returns a ServerStatus struct containing:

  • online: Whether the server is online
  • ip: Resolved IP address
  • port: Server port number
  • hostname: Original hostname used for query
  • latency: Response time in milliseconds
  • dns: Optional DNS information (A records, CNAME, TTL)
  • data: Edition-specific server data (version, players, plugins, etc.)
§Errors

Returns McError if:

§Example
use rust_mc_status::{McClient, ServerEdition};

let client = McClient::new();

// Ping Java server (automatic SRV lookup)
let status = client.ping("mc.hypixel.net", ServerEdition::Java).await?;
println!("Server is online: {}", status.online);
println!("Latency: {:.2}ms", status.latency);

// Ping Bedrock server
let status = client.ping("geo.hivebedrock.network:19132", ServerEdition::Bedrock).await?;
println!("Players: {}/{}", status.players().unwrap_or((0, 0)).0, status.players().unwrap_or((0, 0)).1);
Source

pub async fn ping_java(&self, address: &str) -> Result<ServerStatus, McError>

Ping a Java Edition server and get its status.

This method automatically performs an SRV DNS lookup if no port is specified in the address. The lookup follows the Minecraft client behavior:

  • Queries _minecraft._tcp.{hostname} for SRV records
  • Uses the target host and port from the SRV record if found
  • Falls back to the default port (25565) if no SRV record exists
  • Skips SRV lookup if port is explicitly specified
§Arguments
  • address - Server address in one of the following formats:
    • "hostname" - Hostname without port (performs SRV lookup, defaults to 25565)
    • "hostname:25565" - Hostname with explicit port (skips SRV lookup)
    • "192.168.1.1" - IP address without port (uses port 25565)
    • "192.168.1.1:25565" - IP address with explicit port
§Returns

Returns a ServerStatus with ServerData::Java containing:

  • Version information (name, protocol version)
  • Player information (online count, max players, sample list)
  • Server description (MOTD)
  • Optional favicon (base64-encoded PNG)
  • Optional plugins list
  • Optional mods list
  • Additional metadata (map, gamemode, software)
§Errors

Returns McError if:

§Example
use rust_mc_status::McClient;

let client = McClient::new();

// Automatic SRV lookup (queries _minecraft._tcp.mc.hypixel.net)
let status = client.ping_java("mc.hypixel.net").await?;
if let rust_mc_status::ServerData::Java(java) = &status.data {
    println!("Version: {}", java.version.name);
    println!("Players: {}/{}", java.players.online, java.players.max);
    println!("Description: {}", java.description);
}

// Skip SRV lookup (uses port 25565 directly)
let status = client.ping_java("mc.hypixel.net:25565").await?;
Source

pub async fn ping_bedrock(&self, address: &str) -> Result<ServerStatus, McError>

Ping a Bedrock Edition server and get its status.

Bedrock Edition servers use UDP protocol and typically run on port 19132. This method sends a UDP ping packet and parses the response.

§Arguments
  • address - Server address in one of the following formats:
    • "hostname" - Hostname without port (uses default port 19132)
    • "hostname:19132" - Hostname with explicit port
    • "192.168.1.1" - IP address without port (uses port 19132)
    • "192.168.1.1:19132" - IP address with explicit port
§Returns

Returns a ServerStatus with ServerData::Bedrock containing:

  • Edition information (e.g., “MCPE”)
  • Version information
  • Player counts (online and max)
  • Message of the day (MOTD)
  • Protocol version
  • Server UID
  • Game mode information
  • Port information (IPv4 and IPv6)
  • Optional map name and software
§Errors

Returns McError if:

§Example
use rust_mc_status::McClient;

let client = McClient::new();
let status = client.ping_bedrock("geo.hivebedrock.network:19132").await?;

if let rust_mc_status::ServerData::Bedrock(bedrock) = &status.data {
    println!("Edition: {}", bedrock.edition);
    println!("Version: {}", bedrock.version);
    println!("Players: {}/{}", bedrock.online_players, bedrock.max_players);
    println!("MOTD: {}", bedrock.motd);
}
Source

pub async fn is_online(&self, address: &str, edition: ServerEdition) -> bool

Quick check if a server is online.

This method performs a minimal connection check without retrieving full server status. It’s faster than ping() but provides less information. Use this method when you only need to know if a server is reachable.

§Arguments
  • address - Server address in one of the following formats:
    • "hostname" - Hostname without port (uses default port for edition)
    • "hostname:port" - Hostname with explicit port
    • "192.168.1.1" - IP address without port (uses default port)
    • "192.168.1.1:25565" - IP address with explicit port
  • edition - Server edition: ServerEdition::Java or ServerEdition::Bedrock
§Returns

Returns true if the server is reachable and responds to ping requests, false if the server is offline, unreachable, or times out.

§Performance

This method is faster than ping() because it:

  • Doesn’t parse full server status
  • Doesn’t retrieve player information
  • Doesn’t parse JSON responses (for Java servers)
§Example
use rust_mc_status::{McClient, ServerEdition};

let client = McClient::new();

// Quick check without full status
if client.is_online("mc.hypixel.net", ServerEdition::Java).await {
    println!("Server is online!");
    // Now get full status if needed
    let status = client.ping("mc.hypixel.net", ServerEdition::Java).await?;
    println!("Players: {}/{}", status.players().unwrap_or((0, 0)).0, status.players().unwrap_or((0, 0)).1);
} else {
    println!("Server is offline or unreachable");
}
Source

pub async fn ping_many( &self, servers: &[ServerInfo], ) -> Vec<(ServerInfo, Result<ServerStatus, McError>)>

Ping multiple servers in parallel.

This method queries multiple servers concurrently with a configurable concurrency limit. Results are returned in the same order as input. The concurrency limit is controlled by with_max_parallel.

§Arguments
  • servers - Slice of ServerInfo structures containing:
    • address: Server address (hostname or IP, optionally with port)
    • edition: Server edition (ServerEdition::Java or ServerEdition::Bedrock)
§Returns

Returns a Vec<(ServerInfo, Result<ServerStatus, McError>)> where:

  • Each tuple contains the original ServerInfo and the query result
  • Results are in the same order as the input slice
  • Ok(ServerStatus) contains full server status information
  • Err(McError) contains error information (timeout, DNS error, etc.)
§Performance
  • Queries are executed in parallel up to the configured limit
  • DNS and SRV caches are shared across all queries
  • Failed queries don’t block other queries
  • Use with_max_parallel() to control resource usage
§Example
use rust_mc_status::{McClient, ServerEdition, ServerInfo};

let client = McClient::new()
    .with_max_parallel(5)  // Process up to 5 servers concurrently
    .with_timeout(std::time::Duration::from_secs(5));

let servers = vec![
    ServerInfo {
        address: "mc.hypixel.net".to_string(),
        edition: ServerEdition::Java,
    },
    ServerInfo {
        address: "geo.hivebedrock.network:19132".to_string(),
        edition: ServerEdition::Bedrock,
    },
];

let results = client.ping_many(&servers).await;
for (server, result) in results {
    match result {
        Ok(status) => {
            println!("{}: ✅ Online ({}ms)", server.address, status.latency);
            if let Some((online, max)) = status.players() {
                println!("  Players: {}/{}", online, max);
            }
        }
        Err(e) => println!("{}: ❌ Error - {}", server.address, e),
    }
}

Trait Implementations§

Source§

impl Clone for McClient

Source§

fn clone(&self) -> McClient

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Default for McClient

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more