fix damage

This commit is contained in:
Robin Appelman 2021-08-08 01:32:04 +02:00
commit cdaa164575
6 changed files with 97 additions and 7 deletions

View file

@ -1,3 +1,5 @@
//! Example for creating a handler that combines the output of multiple handlers
use main_error::MainError;
use std::env::args;
use std::fs;

View file

@ -0,0 +1,68 @@
//! Example of creating a custom handler to extract data from the log
use main_error::MainError;
use std::env::args;
use std::fs;
use tf_log_parser::event::DamageEvent;
use tf_log_parser::{
parse_with_handler, EventHandler, GameEvent, RawEventType, SubjectData, SubjectId, SubjectMap,
};
struct HighestDamage {
user: String,
damage: u32,
}
#[derive(Default)]
struct HighestDamageHandler {
current: Option<(SubjectId, u32)>,
}
impl EventHandler for HighestDamageHandler {
type Output = Option<HighestDamage>;
fn does_handle(&self, ty: RawEventType) -> bool {
matches!(ty, RawEventType::Damage)
}
fn handle(&mut self, _time: u32, subject: SubjectId, event: &GameEvent) {
if let GameEvent::Damage(DamageEvent {
damage: Some(damage),
..
}) = event
{
let damage = damage.get();
// note that we leave the name empty for now to prevent needles cloning
match &mut self.current {
Some((_, current_damage)) if damage > *current_damage => {
self.current = Some((subject, damage))
}
None => self.current = Some((subject, damage)),
_ => {}
}
}
}
fn finish(self, subjects: &SubjectMap) -> Self::Output {
self.current.map(|(subject, damage)| {
let user = match &subjects[subject] {
SubjectData::Player { name, .. } => name.clone(),
_ => {
panic!("A non player did the most damage?")
}
};
HighestDamage { user, damage }
})
}
}
fn main() -> Result<(), MainError> {
let path = args().skip(1).next().expect("No path provided");
let content = fs::read_to_string(path)?;
let HighestDamage { user, damage } =
parse_with_handler::<HighestDamageHandler>(&content)?.expect("nobody did any damage?");
println!("highest damage was {} done by {}", user, damage);
Ok(())
}

View file

@ -136,6 +136,12 @@ impl TryFrom<&RawSubject<'_>> for SubjectData {
#[derive(Debug, Hash, Eq, PartialEq)]
pub struct SteamId3(pub SteamID);
impl From<SteamID> for SteamId3 {
fn from(id: SteamID) -> Self {
SteamId3(id)
}
}
impl Serialize for SteamId3 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where

View file

@ -43,11 +43,13 @@ impl<'a, T> GameEventErrTrait<T> for IResult<&str, T> {
}
}
#[derive(Debug)]
pub enum GameEvent<'a> {
ShotFired(ShotFiredEvent<'a>),
ShotHit(ShotHitEvent<'a>),
Damage(DamageEvent<'a>),
Kill(KillEvent<'a>),
KillAssist(KillAssistEvent<'a>),
Say(&'a str),
SayTeam(&'a str),
Healed(HealedEvent<'a>),
@ -65,6 +67,18 @@ impl<'a> GameEvent<'a> {
RawEventType::ShotFired => {
GameEvent::ShotFired(shot_fired_event_parser(raw.params).with_type(raw.ty)?)
}
RawEventType::ShotHit => {
GameEvent::ShotHit(shot_hit_event_parser(raw.params).with_type(raw.ty)?)
}
RawEventType::Damage => {
GameEvent::Damage(damage_event_parser(raw.params).with_type(raw.ty)?)
}
RawEventType::Killed => {
GameEvent::Kill(kill_event_parser(raw.params).with_type(raw.ty)?)
}
RawEventType::KillAssist => {
GameEvent::KillAssist(kill_assist_event_parser(raw.params).with_type(raw.ty)?)
}
RawEventType::SayTeam => GameEvent::SayTeam(raw.params.trim_matches('"')),
RawEventType::Say => GameEvent::Say(raw.params.trim_matches('"')),
RawEventType::Healed => {
@ -122,7 +136,7 @@ fn param_pair_parse(input: &str) -> IResult<&str, (&str, &str)> {
let (input, _) = tag(r#"""#)(input)?;
if open_tag.is_some() {
let (_input, _) = tag("(")(input)?;
let (_input, _) = tag(")")(input)?;
}
Ok((input, (key, value)))
}

View file

@ -1,4 +1,4 @@
use crate::event::{param_parse, param_parse_with, position, quoted, u_int, ParamIter};
use crate::event::{param_parse, param_parse_with, position, u_int, ParamIter};
use crate::raw_event::{subject_parser, RawSubject};
use nom::combinator::opt;
use nom::IResult;
@ -19,9 +19,9 @@ pub struct ShotHitEvent<'a> {
pub weapon: Option<&'a str>,
}
pub fn shot_hit_event_parser(input: &str) -> IResult<&str, ShotFiredEvent> {
pub fn shot_hit_event_parser(input: &str) -> IResult<&str, ShotHitEvent> {
let (input, weapon) = opt(param_parse("weapon"))(input)?;
Ok((input, ShotFiredEvent { weapon }))
Ok((input, ShotHitEvent { weapon }))
}
#[derive(Debug)]
@ -42,8 +42,8 @@ pub fn damage_event_parser(input: &str) -> IResult<&str, DamageEvent> {
};
for (key, value) in ParamIter::new(input) {
match key {
"damage" => event.damage = NonZeroU32::new(quoted(u_int)(value)?.1),
"realdamage" => event.real_damage = NonZeroU32::new(quoted(u_int)(value)?.1),
"damage" => event.damage = NonZeroU32::new(u_int(value)?.1),
"realdamage" => event.real_damage = NonZeroU32::new(u_int(value)?.1),
"weapon" => event.weapon = Some(value.trim_matches('"')),
_ => {}
}

View file

@ -13,7 +13,7 @@ use std::ops::Index;
use thiserror::Error;
mod common;
mod event;
pub mod event;
#[macro_use]
pub mod module;
mod raw_event;