[Generic] Add struct for all extra request settings (#93)

* [Generic] Add struct for all extra request settings

Adds a new struct `ExtraRequestSettings` that contains all possible
extra settings for all protocols, and can be implicitly converted with
`.into()` into each protocol's extra settings type.

This is then used in a new query method
`query_with_timeout_and_extra_settings()` that passes the object on to
the selected protocol.

This also updates the generic example to set some of these generic
settings so that it can be used for certain queries like
"mc.hypixel.net".

* [Minecraft] Add `request_settings` parameter to auto query

This allows generic queries to pass through request settings when using
the `mc` game so that servers like `mc.hypixel.net` will still work when
using auto query.

* Fix generic examples tests (and enable example tests in pre-commit)
This commit is contained in:
Tom 2023-09-04 22:13:12 +00:00 committed by GitHub
parent 76a3ac2f78
commit 6c1fdb1159
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 175 additions and 20 deletions

View file

@ -26,8 +26,12 @@ mod legacy_v1_6;
/// Queries a Minecraft server with all the protocol variants one by one (Java
/// -> Bedrock -> Legacy (1.6 -> 1.4 -> Beta 1.8)).
pub fn query(address: &SocketAddr, timeout_settings: Option<TimeoutSettings>) -> GDResult<JavaResponse> {
if let Ok(response) = query_java(address, timeout_settings.clone(), None) {
pub fn query(
address: &SocketAddr,
timeout_settings: Option<TimeoutSettings>,
request_settings: Option<RequestSettings>,
) -> GDResult<JavaResponse> {
if let Ok(response) = query_java(address, timeout_settings.clone(), request_settings) {
return Ok(response);
}

View file

@ -5,7 +5,7 @@
use crate::{
buffer::Buffer,
protocols::{
types::{CommonPlayer, CommonResponse, GenericPlayer},
types::{CommonPlayer, CommonResponse, ExtraRequestSettings, GenericPlayer},
GenericResponse,
},
GDErrorKind::{InvalidInput, PacketBad, UnknownEnumCast},
@ -110,6 +110,16 @@ impl Default for RequestSettings {
}
}
impl From<ExtraRequestSettings> for RequestSettings {
fn from(value: ExtraRequestSettings) -> Self {
let default = Self::default();
Self {
hostname: value.hostname.unwrap_or(default.hostname),
protocol_version: value.protocol_version.unwrap_or(default.protocol_version),
}
}
}
impl CommonResponse for JavaResponse {
fn as_original(&self) -> GenericResponse { GenericResponse::Minecraft(VersionedResponse::Java(self)) }

View file

@ -15,4 +15,4 @@ pub mod types;
/// Reference: [Server Query](https://developer.valvesoftware.com/wiki/Server_queries)
pub mod valve;
pub use types::{GenericResponse, Protocol};
pub use types::{ExtraRequestSettings, GenericResponse, Protocol};

View file

@ -185,6 +185,82 @@ impl Default for TimeoutSettings {
}
}
/// Generic extra request settings
///
/// Fields of this struct may not be used depending on which protocol is
/// selected, the individual fields link to the specific places they will be
/// used with additional documentation.
///
/// ## Examples
/// Create minecraft settings with builder:
/// ```
/// use gamedig::protocols::{minecraft, ExtraRequestSettings};
/// let mc_settings: minecraft::RequestSettings = ExtraRequestSettings::default().set_hostname("mc.hypixel.net".to_string()).into();
/// ```
///
/// Create valve settings with builder:
/// ```
/// use gamedig::protocols::{valve, ExtraRequestSettings};
/// let valve_settings: valve::GatheringSettings = ExtraRequestSettings::default().set_check_app_id(false).into();
/// ```
#[derive(Clone, Debug, Default)]
pub struct ExtraRequestSettings {
/// The server's hostname.
///
/// Used by:
/// - [minecraft::RequestSettings#structfield.hostname]
pub hostname: Option<String>,
/// The protocol version to use.
///
/// Used by:
/// - [minecraft::RequestSettings#structfield.protocol_version]
pub protocol_version: Option<i32>,
/// Whether to gather player information
///
/// Used by:
/// - [valve::GatheringSettings#structfield.players]
pub gather_players: Option<bool>,
/// Whether to gather rule information.
///
/// Used by:
/// - [valve::GatheringSettings#structfield.rules]
pub gather_rules: Option<bool>,
/// Whether to check if the App ID is valid.
///
/// Used by:
/// - [valve::GatheringSettings#structfield.check_app_id]
pub check_app_id: Option<bool>,
}
impl ExtraRequestSettings {
/// [Sets hostname](ExtraRequestSettings#structfield.hostname)
pub fn set_hostname(mut self, hostname: String) -> Self {
self.hostname = Some(hostname);
self
}
/// [Sets protocol
/// version](ExtraRequestSettings#structfield.protocol_version)
pub fn set_protocol_version(mut self, protocol_version: i32) -> Self {
self.protocol_version = Some(protocol_version);
self
}
/// [Sets gather players](ExtraRequestSettings#structfield.gather_players)
pub fn set_gather_players(mut self, gather_players: bool) -> Self {
self.gather_players = Some(gather_players);
self
}
/// [Sets gather rules](ExtraRequestSettings#structfield.gather_rules)
pub fn set_gather_rules(mut self, gather_rules: bool) -> Self {
self.gather_rules = Some(gather_rules);
self
}
/// [Sets check app ID](ExtraRequestSettings#structfield.check_app_id)
pub fn set_check_app_id(mut self, check_app_id: bool) -> Self {
self.check_app_id = Some(check_app_id);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -235,4 +311,13 @@ mod tests {
assert_eq!(default_settings.get_read(), Some(Duration::from_secs(4)));
assert_eq!(default_settings.get_write(), Some(Duration::from_secs(4)));
}
// Test that extra request settings can be converted
#[test]
fn test_extra_request_settings() {
let settings = ExtraRequestSettings::default();
let _: minecraft::RequestSettings = settings.clone().into();
let _: valve::GatheringSettings = settings.into();
}
}

View file

@ -1,6 +1,6 @@
use std::collections::HashMap;
use crate::protocols::types::{CommonPlayer, CommonResponse, GenericPlayer};
use crate::protocols::types::{CommonPlayer, CommonResponse, ExtraRequestSettings, GenericPlayer};
use crate::GDErrorKind::UnknownEnumCast;
use crate::GDResult;
use crate::{buffer::Buffer, protocols::GenericResponse};
@ -430,6 +430,17 @@ impl Default for GatheringSettings {
}
}
impl From<ExtraRequestSettings> for GatheringSettings {
fn from(value: ExtraRequestSettings) -> Self {
let default = Self::default();
Self {
players: value.gather_players.unwrap_or(default.players),
rules: value.gather_rules.unwrap_or(default.rules),
check_app_id: value.check_app_id.unwrap_or(default.check_app_id),
}
}
}
/// Generic response types that are used by many games, they are the protocol
/// ones, but without the unnecessary bits (example: the **The Ship**-only
/// fields).