This commit is contained in:
Robin Appelman 2022-05-18 19:11:03 +02:00
commit 7a481af84e
4 changed files with 172 additions and 6 deletions

View file

@ -3,6 +3,7 @@ name = "democutter"
version = "0.1.0"
authors = ["Robin Appelman <robin@icewind.nl>"]
edition = "2021"
default-run = "cut"
[lib]
crate-type = ["cdylib", "rlib"]
@ -11,13 +12,17 @@ crate-type = ["cdylib", "rlib"]
name = "cut"
path = "src/cut.rs"
[[bin]]
name = "bookmarks"
path = "src/bookmarks.rs"
[features]
default = ["console_error_panic_hook"]
[dependencies]
bitbuffer = "0.10"
tf-demo-parser = { version = "0.4", git = "https://github.com/demostf/parser" }
#tf-demo-parser = { version = "0.4", path = "../tf-demo-parser" }
#tf-demo-parser = { version = "0.4", git = "https://github.com/demostf/parser" }
tf-demo-parser = { version = "0.4", path = "../tf-demo-parser" }
wasm-bindgen = "0.2.63"
web-sys = { version = "0.3", features = ["console"] }

17
src/bookmarks.rs Normal file
View file

@ -0,0 +1,17 @@
use clap::Parser;
use democutter::bookmarks;
use std::fs;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
/// Path to the demo
path: String,
}
fn main() {
let args = Args::parse();
let file = fs::read(&args.path).unwrap();
let output = bookmarks(&file);
println!("{:?}", output);
}

137
src/highlight.rs Normal file
View file

@ -0,0 +1,137 @@
use std::collections::{BTreeMap, HashMap};
use tf_demo_parser::demo::gameevent_gen::{
GameEvent, RocketJumpEvent, RocketJumpLandedEvent, StickyJumpEvent, StickyJumpLandedEvent,
};
use tf_demo_parser::demo::message::gameevent::GameEventMessage;
use tf_demo_parser::demo::message::packetentities::PacketEntitiesMessage;
use tf_demo_parser::demo::message::usermessage::UserMessage;
use tf_demo_parser::demo::message::Message;
use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
use tf_demo_parser::demo::parser::analyser::{UserId, UserInfo};
use tf_demo_parser::demo::parser::MessageHandler;
use tf_demo_parser::demo::sendprop::{SendPropIdentifier, SendPropValue};
use tf_demo_parser::{MessageType, ParserState, ReadResult, Stream};
#[derive(Debug)]
pub struct Highlight {
pub tick: u32,
pub user: UserId,
pub source: HighlightSource,
}
#[derive(Debug)]
pub enum HighlightSource {
Prec,
AirShot,
}
#[derive(Default)]
pub struct HighlightAnalyser {
highlights: Vec<Highlight>,
explosive_jumping: HashMap<UserId, bool>,
users: BTreeMap<UserId, UserInfo>,
}
impl HighlightAnalyser {
fn is_explosive_jumping(&self, user: UserId) -> bool {
self.explosive_jumping
.get(&user)
.copied()
.unwrap_or_default()
}
fn parse_user_info(&mut self, text: Option<&str>, data: Option<Stream>) -> ReadResult<()> {
if let Some(user_info) =
tf_demo_parser::demo::data::UserInfo::parse_from_string_table(text, data)?
{
self.users
.entry(user_info.player_info.user_id.into())
.and_modify(|info| {
info.entity_id = user_info.entity_id;
})
.or_insert_with(|| user_info.into());
}
Ok(())
}
}
impl MessageHandler for HighlightAnalyser {
type Output = Vec<Highlight>;
fn does_handle(_message_type: MessageType) -> bool {
true
}
fn handle_message(&mut self, message: &Message, tick: u32) {
match message {
Message::GameEvent(GameEventMessage {
event: GameEvent::PlayerHurt(hit),
..
}) if hit.attacker != hit.user_id => {
let user = hit.user_id.into();
if self.is_explosive_jumping(user) && hit.damage_amount > 50 {
dbg!(hit);
self.highlights.push(Highlight {
tick,
user,
source: HighlightSource::AirShot,
})
}
}
Message::GameEvent(GameEventMessage {
event: GameEvent::RocketJump(RocketJumpEvent { user_id, .. }),
..
})
| Message::GameEvent(GameEventMessage {
event: GameEvent::StickyJump(StickyJumpEvent { user_id, .. }),
..
}) => {
let user_id = (*user_id).into();
self.explosive_jumping.insert(user_id, true);
}
Message::GameEvent(GameEventMessage {
event: GameEvent::RocketJumpLanded(RocketJumpLandedEvent { user_id, .. }),
..
})
| Message::GameEvent(GameEventMessage {
event: GameEvent::StickyJumpLanded(StickyJumpLandedEvent { user_id, .. }),
..
}) => {
let user_id = (*user_id).into();
self.explosive_jumping.insert(user_id, false);
}
Message::GameEvent(GameEventMessage {
event: GameEvent::PlayerSpawn(spawn),
..
}) => {
let user_id = spawn.user_id.into();
self.explosive_jumping.insert(user_id, false);
}
Message::UserMessage(UserMessage::SayText2(text)) => {
if text.text == "[P-REC] Bookmark." {
self.highlights.push(Highlight {
tick,
user: text.client,
source: HighlightSource::Prec,
})
}
}
_ => {}
}
}
fn handle_string_entry(&mut self, table: &str, _index: usize, entry: &StringTableEntry) {
if table == "userinfo" {
let _ = self.parse_user_info(
entry.text.as_ref().map(|s| s.as_ref()),
entry.extra_data.as_ref().map(|data| data.data.clone()),
);
}
}
fn into_output(self, _state: &ParserState) -> Self::Output {
dbg!(self.users);
self.highlights
}
}

View file

@ -1,11 +1,13 @@
#![allow(unused_imports)]
mod entity;
mod highlight;
mod mutate;
mod string_tables;
mod utils;
use crate::entity::ActiveEntities;
use crate::highlight::{Highlight, HighlightAnalyser};
use crate::mutate::{MessageMutator, MutatorList, PacketMutator};
use crate::string_tables::StringTablesUpdates;
use crate::utils::set_panic_hook;
@ -16,16 +18,14 @@ use std::convert::TryInto;
use std::iter::once;
use std::mem::take;
use tf_demo_parser::demo::header::Header;
use tf_demo_parser::demo::message::packetentities::UpdateType::Delete;
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntitiesMessage, UpdateType};
use tf_demo_parser::demo::message::usermessage::UserMessageType;
use tf_demo_parser::demo::message::usermessage::{UserMessage, UserMessageType};
use tf_demo_parser::demo::message::{Message, NetTickMessage};
use tf_demo_parser::demo::packet::message::{MessagePacket, MessagePacketMeta};
use tf_demo_parser::demo::packet::stop::StopPacket;
use tf_demo_parser::demo::packet::PacketType::StringTables;
use tf_demo_parser::demo::packet::{Packet, PacketType};
use tf_demo_parser::demo::parser::{DemoHandler, Encode, NullHandler, RawPacketStream};
use tf_demo_parser::{Demo, MessageType};
use tf_demo_parser::{Demo, DemoParser, MessageType};
use wasm_bindgen::prelude::*;
use web_sys::console;
@ -282,3 +282,10 @@ fn net_tick(tick: u32) -> Message<'static> {
std_dev: 263,
})
}
pub fn bookmarks(input: &[u8]) -> Vec<Highlight> {
let demo = Demo::new(&input);
let parser = DemoParser::new_with_analyser(demo.get_stream(), HighlightAnalyser::default());
let (_, highlights) = parser.parse().unwrap();
highlights
}