feat: add savage 2 support (#169)

* feat: savage 2 support

* fix: add savage 2 to definitions

* chore: run rustfmt

* fix: config serde use

* fix: remove needless borrow

* docs: add savage 2 to protocols.md
This commit is contained in:
CosminPerRam 2023-12-10 19:39:26 +02:00 committed by GitHub
parent dd037daa04
commit af8e1e9b1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 148 additions and 57 deletions

View file

@ -0,0 +1,8 @@
/// The implementation.
/// Reference: [Node-GameGig](https://github.com/gamedig/node-gamedig/blob/master/protocols/savage2.js)
pub mod protocol;
/// All types used by the implementation.
pub mod types;
pub use protocol::*;
pub use types::*;

View file

@ -0,0 +1,37 @@
use crate::buffer::{Buffer, Utf8Decoder};
use crate::games::savage2::types::Response;
use crate::protocols::types::TimeoutSettings;
use crate::socket::{Socket, UdpSocket};
use crate::GDResult;
use byteorder::LittleEndian;
use std::net::{IpAddr, SocketAddr};
pub fn query(address: &IpAddr, port: Option<u16>) -> GDResult<Response> { query_with_timeout(address, port, None) }
pub fn query_with_timeout(
address: &IpAddr,
port: Option<u16>,
timeout_settings: Option<TimeoutSettings>,
) -> GDResult<Response> {
let addr = &SocketAddr::new(*address, port.unwrap_or(11235));
let mut socket = UdpSocket::new(addr, &timeout_settings)?;
socket.send(&[0x01])?;
let data = socket.receive(None)?;
let mut buffer = Buffer::<LittleEndian>::new(&data);
buffer.move_cursor(12)?;
Ok(Response {
name: buffer.read_string::<Utf8Decoder>(None)?,
players_online: buffer.read::<u8>()?,
players_maximum: buffer.read::<u8>()?,
time: buffer.read_string::<Utf8Decoder>(None)?,
map: buffer.read_string::<Utf8Decoder>(None)?,
next_map: buffer.read_string::<Utf8Decoder>(None)?,
location: buffer.read_string::<Utf8Decoder>(None)?,
players_minimum: buffer.read::<u8>()?,
game_mode: buffer.read_string::<Utf8Decoder>(None)?,
protocol_version: buffer.read_string::<Utf8Decoder>(None)?,
level_minimum: buffer.read::<u8>()?,
})
}

View file

@ -0,0 +1,30 @@
use crate::protocols::types::CommonResponse;
use crate::protocols::GenericResponse;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Response {
pub name: String,
pub players_online: u8,
pub players_maximum: u8,
pub players_minimum: u8,
pub time: String,
pub map: String,
pub next_map: String,
pub location: String,
pub game_mode: String,
pub protocol_version: String,
pub level_minimum: u8,
}
impl CommonResponse for Response {
fn as_original(&self) -> GenericResponse { GenericResponse::Savage2(self) }
fn name(&self) -> Option<&str> { Some(&self.name) }
fn game_mode(&self) -> Option<&str> { Some(&self.game_mode) }
fn map(&self) -> Option<&str> { Some(&self.map) }
fn players_maximum(&self) -> u32 { self.players_maximum.into() }
fn players_online(&self) -> u32 { self.players_online.into() }
}