feat(protocols): Add more control over gathering additional information (#180)

* protocols: Add more control over gathering additional information

Adds GatherToggle which allows choosing the behaviour for how the query
handles fetching additional information. The choices are:
- DontGather - Don't attempt to fetch information
- AttemptGather - Try to fetch the information but ignore errors
- Required - Try to fetch information and fail if it errors

A handy macro was also added to utils to dispatch additional queries
based on a GatherToggle value.

* Add/Update badge

* protocols: Improve GatherToggle enum names

Co-Authored-By: Cain <75994858+cainthebest@users.noreply.github.com>
Co-Authored-By: CosminPerRam <cosmin.p@live.com>

* Add/Update badge

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Cain <75994858+cainthebest@users.noreply.github.com>
Co-authored-by: CosminPerRam <cosmin.p@live.com>
This commit is contained in:
Tom 2024-01-22 11:36:17 +00:00 committed by GitHub
parent 6d0c25d6ea
commit 89ed19f089
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 195 additions and 64 deletions

View file

@ -2,7 +2,7 @@ use crate::buffer::{Buffer, StringDecoder};
use crate::errors::GDErrorKind::PacketBad;
use crate::protocols::types::TimeoutSettings;
use crate::socket::{Socket, UdpSocket};
use crate::utils::retry_on_timeout;
use crate::utils::{maybe_gather, retry_on_timeout};
use crate::GDResult;
use super::{GatheringSettings, MutatorsAndRules, PacketKind, Players, Response, ServerInfo};
@ -168,24 +168,22 @@ impl Unreal2Protocol {
// Fetch the server info, this can only handle one response packet
let mut server_info = self.query_server_info()?;
let mutators_and_rules = if gather_settings.mutators_and_rules {
let response = self.query_mutators_and_rules()?;
let mutators_and_rules = maybe_gather!(
gather_settings.mutators_and_rules,
self.query_mutators_and_rules()
)
.unwrap_or_default();
if let Some(password) = response.rules.get("GamePassword") {
let string = password.concat().to_lowercase();
server_info.password = string == "true";
}
if let Some(password) = mutators_and_rules.rules.get("GamePassword") {
let string = password.concat().to_lowercase();
server_info.password = string == "true";
}
response
} else {
MutatorsAndRules::default()
};
let players = if gather_settings.players {
self.query_players(Some(&server_info))?
} else {
Players::with_capacity(0)
};
let players = maybe_gather!(
gather_settings.players,
self.query_players(Some(&server_info))
)
.unwrap_or_else(|| Players::with_capacity(0));
// TODO: Handle extra info parsing when we detect certain game types (or maybe
// include that in gather settings).

View file

@ -1,6 +1,6 @@
use crate::buffer::Buffer;
use crate::errors::GDErrorKind::PacketBad;
use crate::protocols::types::{CommonPlayer, CommonResponse, ExtraRequestSettings, GenericPlayer};
use crate::protocols::types::{CommonPlayer, CommonResponse, ExtraRequestSettings, GatherToggle, GenericPlayer};
use crate::protocols::GenericResponse;
use crate::{GDError, GDResult};
@ -209,16 +209,16 @@ impl CommonResponse for Response {
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct GatheringSettings {
pub players: bool,
pub mutators_and_rules: bool,
pub players: GatherToggle,
pub mutators_and_rules: GatherToggle,
}
impl GatheringSettings {
/// Default values are true for both the players and the rules.
/// Default values is attempt both players and rules.
pub const fn default() -> Self {
Self {
players: true,
mutators_and_rules: true,
players: GatherToggle::Try,
mutators_and_rules: GatherToggle::Enforce,
}
}