mirror of
https://github.com/tribufu/rust-gamedig
synced 2026-06-01 09:42:41 +00:00
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:
parent
dd037daa04
commit
af8e1e9b1a
10 changed files with 148 additions and 57 deletions
|
|
@ -88,6 +88,7 @@ pub static GAMES: Map<&'static str, Game> = phf_map! {
|
|||
"q3a" => game!("Quake 3 Arena", 27960, Protocol::Quake(QuakeVersion::Three)),
|
||||
"ror2" => game!("Risk of Rain 2", 27016, Protocol::Valve(Engine::new(632_360))),
|
||||
"rust" => game!("Rust", 27015, Protocol::Valve(Engine::new(252_490))),
|
||||
"savage2" => game!("Savage 2", 11235, Protocol::PROPRIETARY(ProprietaryProtocol::Savage2)),
|
||||
"sco" => game!("Sven Co-op", 27015, Protocol::Valve(Engine::new_gold_src(false))),
|
||||
"sdtd" => game!("7 Days to Die", 26900, Protocol::Valve(Engine::new(251_570))),
|
||||
"sof2" => game!("Soldier of Fortune 2", 20100, Protocol::Quake(QuakeVersion::Three)),
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ pub mod ffow;
|
|||
pub mod jc2m;
|
||||
/// Minecraft
|
||||
pub mod minecraft;
|
||||
/// Savage 2
|
||||
pub mod savage2;
|
||||
/// The Ship
|
||||
pub mod theship;
|
||||
|
||||
|
|
@ -117,6 +119,9 @@ pub fn query_with_timeout_and_extra_settings(
|
|||
}
|
||||
Protocol::PROPRIETARY(protocol) => {
|
||||
match protocol {
|
||||
ProprietaryProtocol::Savage2 => {
|
||||
savage2::query_with_timeout(address, port, timeout_settings).map(Box::new)?
|
||||
}
|
||||
ProprietaryProtocol::TheShip => {
|
||||
theship::query_with_timeout(address, port, timeout_settings).map(Box::new)?
|
||||
}
|
||||
|
|
|
|||
8
crates/lib/src/games/savage2/mod.rs
Normal file
8
crates/lib/src/games/savage2/mod.rs
Normal 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::*;
|
||||
37
crates/lib/src/games/savage2/protocol.rs
Normal file
37
crates/lib/src/games/savage2/protocol.rs
Normal 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>()?,
|
||||
})
|
||||
}
|
||||
30
crates/lib/src/games/savage2/types.rs
Normal file
30
crates/lib/src/games/savage2/types.rs
Normal 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() }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue