1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-03 18:24:05 +02:00
This commit is contained in:
Robin Appelman 2019-02-25 00:30:59 +01:00
commit 4ac2a3cfc6
20 changed files with 907 additions and 0 deletions

416
src/demo/gamevent.rs Normal file
View file

@ -0,0 +1,416 @@
use std::collections::HashMap;
pub struct GameEventDefinition {
id: u32,
name: String,
entries: Vec<GameEventEntry>,
}
pub struct GameEventEntry {
name: String,
kind: GameEventValueType,
}
pub enum GameEventValueType {
String,
Float,
Long,
Short,
Byte,
Boolean,
Local,
}
pub struct GameEvent {
kind: GameEventType,
values: HashMap<String, GameEventValue>,
}
pub enum GameEventValue {
String(String),
Float(f32),
Long(u32),
Short(u16),
Byte(u8),
Boolean(bool),
Local,
}
pub enum GameEventType {
ServerSpawnEvent,
ServerChangelevelFailedEvent,
ServerShutdownEvent,
ServerCvarEvent,
ServerMessageEvent,
ServerAddBanEvent,
ServerRemoveBanEvent,
PlayerConnectEvent,
PlayerConnectClientEvent,
PlayerInfoEvent,
PlayerDisconnectEvent,
PlayerActivateEvent,
PlayerSayEvent,
ClientDisconnectEvent,
ClientBeginConnectEvent,
ClientConnectedEvent,
ClientFullConnectEvent,
HostQuitEvent,
TeamInfoEvent,
TeamScoreEvent,
TeamPlayBroadcastAudioEvent,
PlayerTeamEvent,
PlayerClassEvent,
PlayerDeathEvent,
PlayerHurtEvent,
PlayerChatEvent,
PlayerScoreEvent,
PlayerSpawnEvent,
PlayerShootEvent,
PlayerUseEvent,
PlayerChangeNameEvent,
PlayerHintMessageEvent,
BasePlayerTeleportedEvent,
GameInitEvent,
GameNewMapEvent,
GameStartEvent,
GameEndEvent,
RoundStartEvent,
RoundEndEvent,
GameMessageEvent,
BreakBreakableEvent,
BreakPropEvent,
EntityKilledEvent,
BonusUpdatedEvent,
AchievementEventEvent,
AchievementIncrementEvent,
PhysgunPickupEvent,
FlareIgniteNpcEvent,
HelicopterGrenadePuntMissEvent,
UserDataDownloadedEvent,
RagdollDissolvedEvent,
HLTVChangedModeEvent,
HLTVChangedTargetEvent,
VoteEndedEvent,
VoteStartedEvent,
VoteChangedEvent,
VotePassedEvent,
VoteFailedEvent,
VoteCastEvent,
VoteOptionsEvent,
ReplaySavedEvent,
EnteredPerformanceModeEvent,
BrowseReplaysEvent,
ReplayYoutubeStatsEvent,
InventoryUpdatedEvent,
CartUpdatedEvent,
StorePricesheetUpdatedEvent,
GcConnectedEvent,
ItemSchemaInitializedEvent,
IntroFinishEvent,
IntroNextCameraEvent,
MmLobbyChatEvent,
MmLobbyMemberJoinEvent,
MmLobbyMemberLeaveEvent,
PlayerChangeClassEvent,
TfMapTimeRemainingEvent,
TfGameOverEvent,
CtfFlagCapturedEvent,
ControlPointInitializedEvent,
ControlPointUpdateImagesEvent,
ControlPointUpdateLayoutEvent,
ControlPointUpdateCappingEvent,
ControlPointUpdateOwnerEvent,
ControlPointStartTouchEvent,
ControlPointEndTouchEvent,
ControlPointPulseElementEvent,
ControlPointFakeCaptureEvent,
ControlPointFakeCaptureMultEvent,
TeamPlayRoundSelectedEvent,
TeamPlayRoundStartEvent,
TeamPlayRoundActiveEvent,
TeamPlayWaitingBeginsEvent,
TeamPlayWaitingEndsEvent,
TeamPlayWaitingAboutToEndEvent,
TeamPlayRestartRoundEvent,
TeamPlayReadyRestartEvent,
TeamPlayRoundRestartSecondsEvent,
TeamPlayTeamReadyEvent,
TeamPlayRoundWinEvent,
TeamPlayUpdateTimerEvent,
TeamPlayRoundStalemateEvent,
TeamPlayOvertimeBeginEvent,
TeamPlayOvertimeEndEvent,
TeamPlaySuddenDeathBeginEvent,
TeamPlaySuddenDeathEndEvent,
TeamPlayGameOverEvent,
TeamPlayMapTimeRemainingEvent,
TeamPlayTimerFlashEvent,
TeamPlayTimerTimeAddedEvent,
TeamPlayPointStartCaptureEvent,
TeamPlayPointCapturedEvent,
TeamPlayPointLockedEvent,
TeamPlayPointUnlockedEvent,
TeamPlayCaptureBrokenEvent,
TeamPlayCaptureBlockedEvent,
TeamPlayFlagEventEvent,
TeamPlayWinPanelEvent,
TeamPlayTeambalancedPlayerEvent,
TeamPlaySetupFinishedEvent,
TeamPlayAlertEvent,
TrainingCompleteEvent,
ShowFreezePanelEvent,
HideFreezePanelEvent,
FreezeCamStartedEvent,
LocalPlayerChangeTeamEvent,
LocalPlayerScoreChangedEvent,
LocalPlayerChangeClassEvent,
LocalPlayerRespawnEvent,
BuildingInfoChangedEvent,
LocalPlayerChangeDisguiseEvent,
PlayerAccountChangedEvent,
SpyPdaResetEvent,
FlagStatusUpdateEvent,
PlayerStatsUpdatedEvent,
PlayingCommentaryEvent,
PlayerChargedeployedEvent,
PlayerBuiltObjectEvent,
PlayerUpgradedObjectEvent,
PlayerCarryObjectEvent,
PlayerDropObjectEvent,
ObjectRemovedEvent,
ObjectDestroyedEvent,
ObjectDetonatedEvent,
AchievementEarnedEvent,
SpecTargetUpdatedEvent,
TournamentStateUpdateEvent,
TournamentEnableCountdownEvent,
PlayerCalledForMedicEvent,
PlayerAskedForBallEvent,
LocalPlayerBecameObserverEvent,
PlayerIgnitedInvEvent,
PlayerIgnitedEvent,
PlayerExtinguishedEvent,
PlayerTeleportedEvent,
PlayerHealedMedicCallEvent,
LocalPlayerChargeReadyEvent,
LocalPlayerWinddownEvent,
PlayerInvulnedEvent,
EscortSpeedEvent,
EscortProgressEvent,
EscortRecedeEvent,
GameUIActivatedEvent,
GameUIHiddenEvent,
PlayerEscortScoreEvent,
PlayerHealOnHitEvent,
PlayerStealsandvichEvent,
ShowClassLayoutEvent,
ShowVsPanelEvent,
PlayerDamagedEvent,
ArenaPlayerNotificationEvent,
ArenaMatchMaxStreakEvent,
ArenaRoundStartEvent,
ArenaWinPanelEvent,
PveWinPanelEvent,
AirDashEvent,
LandedEvent,
PlayerDamageDodgedEvent,
PlayerStunnedEvent,
ScoutGrandSlamEvent,
ScoutSlamdollLandedEvent,
ArrowImpactEvent,
PlayerJaratedEvent,
PlayerJaratedFadeEvent,
PlayerShieldBlockedEvent,
PlayerPinnedEvent,
PlayerHealedByMedicEvent,
PlayerSappedObjectEvent,
ItemFoundEvent,
ShowAnnotationEvent,
HideAnnotationEvent,
PostInventoryApplicationEvent,
ControlPointUnlockUpdatedEvent,
DeployBuffBannerEvent,
PlayerBuffEvent,
MedicDeathEvent,
OvertimeNagEvent,
TeamsChangedEvent,
HalloweenPumpkinGrabEvent,
RocketJumpEvent,
RocketJumpLandedEvent,
StickyJumpEvent,
StickyJumpLandedEvent,
MedicDefendedEvent,
LocalPlayerHealedEvent,
PlayerDestroyedPipeBombEvent,
ObjectDeflectedEvent,
PlayerMvpEvent,
RaidSpawnMobEvent,
RaidSpawnSquadEvent,
NavBlockedEvent,
PathTrackPassedEvent,
NumCappersChangedEvent,
PlayerRegenerateEvent,
UpdateStatusItemEvent,
StatsResetRoundEvent,
ScoreStatsAccumulatedUpdateEvent,
ScoreStatsAccumulatedResetEvent,
AchievementEarnedLocalEvent,
PlayerHealedEvent,
BuildingHealedEvent,
ItemPickupEvent,
DuelStatusEvent,
FishNoticeEvent,
FishNoticeArmEvent,
ThrowableHitEvent,
PumpkinLordSummonedEvent,
PumpkinLordKilledEvent,
MerasmusSummonedEvent,
MerasmusKilledEvent,
MerasmusEscapeWarningEvent,
MerasmusEscapedEvent,
EyeballBossSummonedEvent,
EyeballBossStunnedEvent,
EyeballBossKilledEvent,
EyeballBossKillerEvent,
EyeballBossEscapeImminentEvent,
EyeballBossEscapedEvent,
NpcHurtEvent,
ControlPointTimerUpdatedEvent,
PlayerHighfiveStartEvent,
PlayerHighfiveCancelEvent,
PlayerHighfiveSuccessEvent,
PlayerBonusPointsEvent,
PlayerUpgradedEvent,
PlayerBuybackEvent,
PlayerUsedPowerUpBottleEvent,
ChristmasGiftGrabEvent,
PlayerKilledAchievementZoneEvent,
PartyUpdatedEvent,
LobbyUpdatedEvent,
MvmMissionUpdateEvent,
RecalculateHolidaysEvent,
PlayerCurrencyChangedEvent,
DoomsdayRocketOpenEvent,
RemoveNemesisRelationshipsEvent,
MvmCreditBonusWaveEvent,
MvmCreditBonusAllEvent,
MvmCreditBonusAllAdvancedEvent,
MvmQuickSentryUpgradeEvent,
MvmTankDestroyedByPlayersEvent,
MvmKillRobotDeliveringBombEvent,
MvmPickupCurrencyEvent,
MvmBombCarrierKilledEvent,
MvmSentryBusterDetonateEvent,
MvmScoutMarkedForDeathEvent,
MvmMedicPowerupSharedEvent,
MvmBeginWaveEvent,
MvmWaveCompleteEvent,
MvmMissionCompleteEvent,
MvmBombResetByPlayerEvent,
MvmBombAlarmTriggeredEvent,
MvmBombDeployResetByPlayerEvent,
MvmWaveFailedEvent,
MvmResetStatsEvent,
DamageResistedEvent,
RevivePlayerNotifyEvent,
RevivePlayerStoppedEvent,
RevivePlayerCompleteEvent,
PlayerTurnedToGhostEvent,
MedigunShieldBlockedDamageEvent,
MvmAdvWaveCompleteNoGatesEvent,
MvmSniperHeadshotCurrencyEvent,
MvmMannhattanPitEvent,
FlagCarriedInDetectionZoneEvent,
MvmAdvWaveKilledStunRadioEvent,
PlayerDirecthitStunEvent,
MvmSentryBusterKilledEvent,
UpgradesFileChangedEvent,
RdTeamPointsChangedEvent,
RdRulesStateChangedEvent,
RdRobotKilledEvent,
RdRobotImpactEvent,
TeamPlayPreRoundTimeLeftEvent,
ParachuteDeployEvent,
ParachuteHolsterEvent,
KillRefillsMeterEvent,
RpsTauntEventEvent,
CongaKillEvent,
PlayerInitialSpawnEvent,
CompetitiveVictoryEvent,
CompetitiveStatsUpdateEvent,
MiniGameWinEvent,
SentryOnGoActiveEvent,
DuckXpLevelUpEvent,
QuestLogOpenedEvent,
SchemaUpdatedEvent,
LocalPlayerPickupWeaponEvent,
RdPlayerScorePointsEvent,
DemomanDetStickiesEvent,
QuestObjectiveCompletedEvent,
PlayerScoreChangedEvent,
KilledCappingPlayerEvent,
EnvironmentalDeathEvent,
ProjectileDirectHitEvent,
PassGetEvent,
PassScoreEvent,
PassFreeEvent,
PassPassCaughtEvent,
PassBallStolenEvent,
PassBallBlockedEvent,
DamagePreventedEvent,
HalloweenBossKilledEvent,
EscapedLootIslandEvent,
TaggedPlayerAsItEvent,
MerasmusStunnedEvent,
MerasmusPropFoundEvent,
HalloweenSkeletonKilledEvent,
EscapeHellEvent,
CrossSpectralBridgeEvent,
MiniGameWonEvent,
RespawnGhostEvent,
KillInHellEvent,
HalloweenDuckCollectedEvent,
SpecialScoreEvent,
TeamLeaderKilledEvent,
HalloweenSoulCollectedEvent,
RecalculateTruceEvent,
DeadringerCheatDeathEvent,
CrossbowHealEvent,
DamageMitigatedEvent,
PayloadPushedEvent,
PlayerAbandonedMatchEvent,
ClDrawlineEvent,
RestartTimerTimeEvent,
WinLimitChangedEvent,
WinPanelShowScoresEvent,
TopStreamsRequestFinishedEvent,
CompetitiveStateChangedEvent,
GlobalWarDataUpdatedEvent,
StopWatchChangedEvent,
DsStopEvent,
DsScreenshotEvent,
ShowMatchSummaryEvent,
ExperienceChangedEvent,
BeginXpLerpEvent,
MatchmakerStatsUpdatedEvent,
RematchVotePeriodOverEvent,
RematchFailedToCreateEvent,
PlayerRematchChangeEvent,
PingUpdatedEvent,
PlayerNextMapVoteChangeEvent,
VoteMapsChangedEvent,
HLTVStatusEvent,
HLTVCameramanEvent,
HLTVRankCameraEvent,
HLTVRankEntityEvent,
HLTVFixedEvent,
HLTVChaseEvent,
HLTVMessageEvent,
HLTVTitleEvent,
HLTVChatEvent,
ReplayStartRecordEvent,
ReplaySessionInfoEvent,
ReplayEndRecordEvent,
ReplayReplaysAvailableEvent,
ReplayServerErrorEvent,
}

62
src/demo/header.rs Normal file
View file

@ -0,0 +1,62 @@
use crate::{ParseError, Parse, Result, Stream, ParserState};
//use crate::test::test_parse;
#[derive(Debug, PartialEq)]
pub struct Header {
pub demo_type: String,
pub version: u32,
pub protocol: u32,
pub server: String,
pub nick: String,
pub map: String,
pub game: String,
pub duration: f32,
pub ticks: u32,
pub frames: u32,
pub sigon: u32,
}
impl<'a> Parse<'a> for Header {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Header> {
Ok(Header {
demo_type: stream.read_string(Some(8))?,
version: stream.read(32)?,
protocol: stream.read(32)?,
server: stream.read_string(Some(260))?,
nick: stream.read_string(Some(260))?,
map: stream.read_string(Some(260))?,
game: stream.read_string(Some(260))?,
duration: stream.read_float()?,
ticks: stream.read(32)?,
frames: stream.read(32)?,
sigon: stream.read(32)?,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
stream
.skip(8 * 8 + (32 * 2) + (260 * 8 * 4) + (32 * 4))
.map_err(ParseError::from)
}
}
//#[test]
//fn test_header() {
// test_parse(
// "data/small.dem",
// Header {
// demo_type: "HL2DEMO".to_owned(),
// version: 3,
// protocol: 24,
// server: "localhost:27015".to_owned(),
// nick: "Icewind | demos.tf".to_owned(),
// map: "cp_gullywash".to_owned(),
// game: "tf".to_owned(),
// duration: 1.7249999,
// ticks: 115,
// frames: 111,
// sigon: 218908,
// },
// 0,
// );
//}

40
src/demo/mod.rs Normal file
View file

@ -0,0 +1,40 @@
use bitstream_reader::{BitBuffer, BitStream, LittleEndian, NonPadded};
use rentals::OwnedBuffer;
pub mod gamevent;
pub mod header;
pub mod sendprop;
pub mod vector;
pub mod parser;
pub mod packet;
pub type Buffer<'a> = BitBuffer<'a, LittleEndian, NonPadded>;
pub type Stream<'a> = BitStream<'a, LittleEndian, NonPadded>;
rental! {
mod rentals {
use super::*;
#[rental_mut(covariant)]
pub struct OwnedBuffer {
source_vec: Vec<u8>,
stream: Buffer<'source_vec>,
}
}
}
pub struct Demo {
data: OwnedBuffer,
}
impl Demo {
pub fn new(vec: Vec<u8>) -> Self {
let data = OwnedBuffer::new(vec, |bytes| BitBuffer::new(bytes, LittleEndian));
Demo { data }
}
/// Get a new stream with the data of the demo
pub fn get_stream(&self) -> Stream {
BitStream::new(self.data.suffix().clone(), None, None)
}
}

View file

@ -0,0 +1,23 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
pub struct ConsoleCmdPacket {
tick: u32,
command: String,
}
impl<'a> Parse<'a> for ConsoleCmdPacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let tick = stream.read(32)?;
let len = stream.read(32)?;
Ok(ConsoleCmdPacket {
tick,
command: stream.read_string(Some(len))?,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(32)?;
let len = stream.read(32)?;
stream.skip(len).map_err(ParseError::from)
}
}

46
src/demo/packet/mod.rs Normal file
View file

@ -0,0 +1,46 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use num_traits::FromPrimitive;
use self::stop::Stop;
mod stop;
mod synctick;
mod consolecmd;
mod usercmd;
mod stringtable;
pub enum Packet {
Stop(Stop)
}
#[derive(Primitive)]
pub enum PacketType {
Sigon = 1,
Packet = 2,
SyncTick = 3,
ConsoleCmd = 4,
UserCmd = 5,
DataTables = 6,
Stop = 7,
StringTables = 8,
}
impl Packet {
fn read_type(stream: &mut Stream) -> Result<PacketType> {
let raw = stream.read(8)?;
let packet_type: Option<PacketType> = PacketType::from_u8(raw);
packet_type.ok_or(ParseError::InvalidPacketType(raw))
}
}
//impl Parse for Packet {
// fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
// let packet_type = Packet::read_type(stream);
// match packet_type {
// Sigon => {}
// }
// }
//
// fn skip(stream: &mut Stream) -> Result<()> {
// Ok(())
// }
//}

13
src/demo/packet/stop.rs Normal file
View file

@ -0,0 +1,13 @@
use crate::{Parse, ParserState, Result, Stream};
pub struct Stop;
impl<'a> Parse<'a> for Stop {
fn parse(_stream: &mut Stream, _state: &ParserState) -> Result<Self> {
Ok(Stop)
}
fn skip(_stream: &mut Stream) -> Result<()> {
Ok(())
}
}

View file

@ -0,0 +1,91 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
pub struct StringTable<'a> {
name: String,
entries: Vec<StringTableEntry<'a>>,
max_entries: u32,
fixed_userdata_size: Option<u32>,
fixed_userdata_size_bits: Option<u32>,
client_entries: Option<Vec<StringTableEntry<'a>>>,
compressed: bool,
}
impl<'a> StringTable<'a> {
fn parse(stream: &mut Stream<'a>) -> Result<Self> {
let name = stream.read_string(None)?;
let entry_count: u32 = stream.read(16)?;
let mut entries = Vec::with_capacity(entry_count as usize);
for _ in 0..entry_count {
entries.push(StringTableEntry::parse(stream)?);
}
let client_entries = if stream.read_bool()? {
let count = stream.read(16)?;
let mut vec = Vec::with_capacity(count);
for _ in 0..count {
vec.push(StringTableEntry::parse(stream)?);
}
Some(vec)
} else {
None
};
Ok(StringTable {
name,
entries,
max_entries: entry_count,
fixed_userdata_size: None,
fixed_userdata_size_bits: None,
client_entries,
compressed: false,
})
}
}
pub struct StringTableEntry<'a> {
text: String,
extra_data: Option<Stream<'a>>,
}
impl<'a> StringTableEntry<'a> {
fn parse(stream: &mut Stream<'a>) -> Result<Self> {
let text = stream.read_string(None)?;
let extra_data = if stream.read_bool()? {
let byte_len: usize = stream.read(16)?;
Some(stream.read_bits(byte_len * 8)?)
} else {
None
};
Ok(StringTableEntry {
text,
extra_data,
})
}
}
pub struct StringTablePacket<'a> {
tick: u32,
tables: Vec<StringTable<'a>>,
}
impl<'a> Parse<'a> for StringTablePacket<'a> {
fn parse(stream: &mut Stream<'a>, _state: &ParserState<'a>) -> Result<Self> {
let tick = stream.read(32)?;
let length: usize = stream.read(32)?;
let count: u32 = stream.read(8)?;
let mut tables = Vec::with_capacity(count as usize);
for _ in 0..count {
tables.push(StringTable::parse(stream)?);
}
Ok(StringTablePacket {
tick,
tables,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(32)?;
let length = stream.read(32)?;
stream.skip(length).map_err(ParseError::from)
}
}

View file

@ -0,0 +1,17 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
pub struct SyncTickPacket {
tick: u32
}
impl<'a> Parse<'a> for SyncTickPacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
Ok(SyncTickPacket {
tick: stream.read(32)?
})
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(32).map_err(ParseError::from)
}
}

View file

@ -0,0 +1,26 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
pub struct UserCmdPacket {
tick: u32,
command: String,
sequence_out: u32
}
impl<'a> Parse<'a> for UserCmdPacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let tick = stream.read(32)?;
let sequence_out = stream.read(32)?;
let len = stream.read(32)?;
Ok(UserCmdPacket {
tick,
sequence_out,
command: stream.read_string(Some(len))?,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(64)?;
let len = stream.read(32)?;
stream.skip(len).map_err(ParseError::from)
}
}

59
src/demo/parser/mod.rs Normal file
View file

@ -0,0 +1,59 @@
use bitstream_reader::ReadError;
pub use crate::demo::parser::state::ParserState;
use crate::Stream;
mod state;
/// Errors that can occur during parsing
#[derive(Debug)]
pub enum ParseError {
/// Error while reading bits from stream
ReadError(ReadError),
/// Packet identifier is invalid
InvalidPacketType(u8),
}
impl From<ReadError> for ParseError {
fn from(err: ReadError) -> ParseError {
ParseError::ReadError(err)
}
}
pub type Result<T> = std::result::Result<T, ParseError>;
pub trait Parse<'a>: Sized {
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self>;
fn skip(stream: &mut Stream) -> Result<()>;
}
pub struct DemoParser<'a> {
stream: Stream<'a>,
state: ParserState<'a>,
}
impl<'a> DemoParser<'a> {
pub fn new(stream: Stream<'a>) -> Self {
DemoParser {
state: ParserState::new(&stream),
stream,
}
}
pub fn read<T: Parse<'a>>(&mut self) -> Result<T> {
T::parse(&mut self.stream, &self.state)
}
pub fn skip<T: Parse<'a>>(&mut self) -> Result<()> {
T::skip(&mut self.stream)
}
pub fn stream_pos(&self) -> usize {
self.stream.pos()
}
pub fn set_stream_pos(&mut self, pos: usize) -> Result<()> {
self.stream.set_pos(pos)?;
Ok(())
}
}

26
src/demo/parser/state.rs Normal file
View file

@ -0,0 +1,26 @@
use crate::demo::gamevent::GameEventDefinition;
use crate::demo::sendprop::SendProp;
use std::collections::HashMap;
use crate::Stream;
pub struct ParserState<'a> {
pub version: u32,
pub static_baselines: HashMap<u32, StaticBaseline<'a>>,
pub event_definitions: HashMap<u32, GameEventDefinition>,
}
pub struct StaticBaseline<'a> {
class_id: u32,
raw: Stream<'a>,
parsed: Option<Vec<SendProp>>,
}
impl<'a> ParserState<'a> {
pub fn new(_stream: &Stream<'a>) -> Self {
ParserState {
version: 0,
static_baselines: HashMap::new(),
event_definitions: HashMap::new(),
}
}
}

17
src/demo/sendprop.rs Normal file
View file

@ -0,0 +1,17 @@
use super::vector::{Vector, VectorXY};
pub struct SendPropDefinition {}
pub enum SendPropType {
Vector(Vector),
VectorXY(VectorXY),
Integer(i32),
Float(f32),
String(String),
Array(Vec<SendPropType>),
}
pub struct SendProp {
definition: SendPropDefinition,
value: SendPropType,
}

10
src/demo/vector.rs Normal file
View file

@ -0,0 +1,10 @@
pub struct Vector {
pub x: f32,
pub y: f32,
pub z: f32,
}
pub struct VectorXY {
pub x: f32,
pub y: f32,
}