mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
handle older serverinfo messages
This commit is contained in:
parent
442c4963f6
commit
4bd97e4afc
3 changed files with 153 additions and 32 deletions
|
|
@ -53,28 +53,6 @@ pub struct PrintMessage {
|
|||
pub value: MaybeUtf8String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
pub struct ServerInfoMessage {
|
||||
pub version: u16,
|
||||
pub server_count: u32,
|
||||
pub stv: bool,
|
||||
pub dedicated: bool,
|
||||
pub max_crc: u32,
|
||||
pub max_classes: u16,
|
||||
pub map_hash: [u8; 16],
|
||||
pub player_slot: u8,
|
||||
pub max_player_count: u8,
|
||||
pub interval_per_tick: f32,
|
||||
#[size = 1]
|
||||
pub platform: String,
|
||||
pub game: String,
|
||||
pub map: String,
|
||||
pub skybox: String,
|
||||
pub server_name: String,
|
||||
pub replay: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
pub struct SetPauseMessage {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
pub use generated::*;
|
||||
|
||||
use crate::demo::message::bspdecal::*;
|
||||
use crate::demo::message::classinfo::*;
|
||||
use crate::demo::message::gameevent::*;
|
||||
use crate::demo::message::packetentities::*;
|
||||
use crate::demo::message::setconvar::*;
|
||||
use crate::demo::message::stringtable::*;
|
||||
use crate::demo::message::tempentities::*;
|
||||
use crate::demo::message::usermessage::*;
|
||||
use crate::demo::message::voice::*;
|
||||
use crate::demo::message::prefetch::*;
|
||||
pub use crate::demo::message::bspdecal::*;
|
||||
pub use crate::demo::message::classinfo::*;
|
||||
pub use crate::demo::message::gameevent::*;
|
||||
pub use crate::demo::message::packetentities::*;
|
||||
pub use crate::demo::message::setconvar::*;
|
||||
pub use crate::demo::message::stringtable::*;
|
||||
pub use crate::demo::message::tempentities::*;
|
||||
pub use crate::demo::message::usermessage::*;
|
||||
pub use crate::demo::message::voice::*;
|
||||
pub use crate::demo::message::prefetch::*;
|
||||
pub use crate::demo::message::serverinfo::*;
|
||||
use crate::demo::parser::{Encode, ParseBitSkip};
|
||||
use crate::{Parse, ParserState, Result, Stream};
|
||||
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
|
||||
|
|
@ -27,6 +28,7 @@ pub mod tempentities;
|
|||
pub mod usermessage;
|
||||
pub mod voice;
|
||||
pub mod prefetch;
|
||||
mod serverinfo;
|
||||
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema_repr))]
|
||||
#[derive(
|
||||
|
|
|
|||
141
src/demo/message/serverinfo.rs
Normal file
141
src/demo/message/serverinfo.rs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
use crate::demo::parser::{Encode, ParseBitSkip};
|
||||
use crate::{Parse, ParserState, Result, Stream};
|
||||
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
pub struct ServerInfoMessage {
|
||||
pub version: u16,
|
||||
pub server_count: u32,
|
||||
pub stv: bool,
|
||||
pub dedicated: bool,
|
||||
pub max_crc: u32,
|
||||
pub max_classes: u16,
|
||||
pub map_hash: [u8; 16],
|
||||
pub player_slot: u8,
|
||||
pub max_player_count: u8,
|
||||
pub interval_per_tick: f32,
|
||||
pub platform: String,
|
||||
pub game: String,
|
||||
pub map: String,
|
||||
pub skybox: String,
|
||||
pub server_name: String,
|
||||
pub replay: bool,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for ServerInfoMessage {
|
||||
fn parse(stream: &mut Stream<'a>, state: &ParserState) -> Result<Self> {
|
||||
let part1 = ServerInfoMessagePart1::read(stream)?;
|
||||
let map_hash = if state.protocol_version > 17 {
|
||||
<[u8; 16]>::read(stream)?
|
||||
} else {
|
||||
let mut hash = [0; 16];
|
||||
let crc = u32::read(stream)?;
|
||||
hash[0..4].copy_from_slice(&crc.to_le_bytes());
|
||||
hash
|
||||
};
|
||||
let part2 = ServerInfoMessagePart2::read(stream)?;
|
||||
let replay = if state.protocol_version > 15 {
|
||||
bool::read(stream)?
|
||||
} else {
|
||||
false
|
||||
};
|
||||
Ok(ServerInfoMessage {
|
||||
version: part1.version,
|
||||
server_count: part1.server_count,
|
||||
stv: part1.stv,
|
||||
dedicated: part1.dedicated,
|
||||
max_crc: part1.max_crc,
|
||||
max_classes: part1.max_classes,
|
||||
map_hash,
|
||||
player_slot: part2.player_slot,
|
||||
max_player_count: part2.max_player_count,
|
||||
interval_per_tick: part2.interval_per_tick,
|
||||
platform: part2.platform,
|
||||
game: part2.game,
|
||||
map: part2.map,
|
||||
skybox: part2.skybox,
|
||||
server_name: part2.server_name,
|
||||
replay,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ParseBitSkip<'a> for ServerInfoMessage {
|
||||
fn parse_skip(stream: &mut Stream<'a>, state: &ParserState) -> Result<()> {
|
||||
let version_dependent_size = match state.protocol_version {
|
||||
0..=15 => 4 * 8, // only the 4 byte crc
|
||||
16..=17 => 4 * 8 + 1, // adds the 1 bit replay flag
|
||||
18.. => 16 * 8 + 1, // replaces 4 byte crc with an 16 byte hash
|
||||
};
|
||||
let size = <ServerInfoMessagePart1 as BitRead<LittleEndian>>::bit_size().unwrap_or_default()
|
||||
+ <ServerInfoMessagePart2 as BitRead<LittleEndian>>::bit_size().unwrap_or_default()
|
||||
+ version_dependent_size;
|
||||
stream.skip_bits(size)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for ServerInfoMessage {
|
||||
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
|
||||
let part1 = ServerInfoMessagePart1 {
|
||||
version: self.version,
|
||||
server_count: self.server_count,
|
||||
stv: self.stv,
|
||||
dedicated: self.dedicated,
|
||||
max_crc: self.max_crc,
|
||||
max_classes: self.max_classes,
|
||||
};
|
||||
part1.write(stream)?;
|
||||
if state.protocol_version > 17 {
|
||||
self.map_hash.write(stream)?;
|
||||
} else {
|
||||
let crc = u32::from_le_bytes([
|
||||
self.map_hash[0],
|
||||
self.map_hash[1],
|
||||
self.map_hash[2],
|
||||
self.map_hash[3],
|
||||
]);
|
||||
crc.write(stream)?;
|
||||
};
|
||||
let part2 = ServerInfoMessagePart2 {
|
||||
player_slot: self.player_slot,
|
||||
max_player_count: self.max_player_count,
|
||||
interval_per_tick: self.interval_per_tick,
|
||||
platform: self.platform.clone(),
|
||||
game: self.game.clone(),
|
||||
map: self.map.clone(),
|
||||
skybox: self.skybox.clone(),
|
||||
server_name: self.server_name.clone(),
|
||||
};
|
||||
part2.write(stream)?;
|
||||
if state.protocol_version > 15 {
|
||||
self.replay.write(stream)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(BitRead, BitWrite)]
|
||||
pub struct ServerInfoMessagePart1 {
|
||||
pub version: u16,
|
||||
pub server_count: u32,
|
||||
pub stv: bool,
|
||||
pub dedicated: bool,
|
||||
pub max_crc: u32,
|
||||
pub max_classes: u16,
|
||||
}
|
||||
|
||||
#[derive(BitRead, BitWrite)]
|
||||
pub struct ServerInfoMessagePart2 {
|
||||
pub player_slot: u8,
|
||||
pub max_player_count: u8,
|
||||
pub interval_per_tick: f32,
|
||||
#[size = 1]
|
||||
pub platform: String,
|
||||
pub game: String,
|
||||
pub map: String,
|
||||
pub skybox: String,
|
||||
pub server_name: String,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue