mirror of
https://github.com/demostf/cutter.git
synced 2026-06-03 11:54:08 +02:00
bumb
This commit is contained in:
parent
d151938cc8
commit
7a481af84e
4 changed files with 172 additions and 6 deletions
|
|
@ -3,6 +3,7 @@ name = "democutter"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Robin Appelman <robin@icewind.nl>"]
|
authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
default-run = "cut"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
@ -11,13 +12,17 @@ crate-type = ["cdylib", "rlib"]
|
||||||
name = "cut"
|
name = "cut"
|
||||||
path = "src/cut.rs"
|
path = "src/cut.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "bookmarks"
|
||||||
|
path = "src/bookmarks.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["console_error_panic_hook"]
|
default = ["console_error_panic_hook"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitbuffer = "0.10"
|
bitbuffer = "0.10"
|
||||||
tf-demo-parser = { version = "0.4", git = "https://github.com/demostf/parser" }
|
#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", path = "../tf-demo-parser" }
|
||||||
wasm-bindgen = "0.2.63"
|
wasm-bindgen = "0.2.63"
|
||||||
web-sys = { version = "0.3", features = ["console"] }
|
web-sys = { version = "0.3", features = ["console"] }
|
||||||
|
|
||||||
|
|
|
||||||
17
src/bookmarks.rs
Normal file
17
src/bookmarks.rs
Normal 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
137
src/highlight.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/lib.rs
15
src/lib.rs
|
|
@ -1,11 +1,13 @@
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
mod entity;
|
mod entity;
|
||||||
|
mod highlight;
|
||||||
mod mutate;
|
mod mutate;
|
||||||
mod string_tables;
|
mod string_tables;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use crate::entity::ActiveEntities;
|
use crate::entity::ActiveEntities;
|
||||||
|
use crate::highlight::{Highlight, HighlightAnalyser};
|
||||||
use crate::mutate::{MessageMutator, MutatorList, PacketMutator};
|
use crate::mutate::{MessageMutator, MutatorList, PacketMutator};
|
||||||
use crate::string_tables::StringTablesUpdates;
|
use crate::string_tables::StringTablesUpdates;
|
||||||
use crate::utils::set_panic_hook;
|
use crate::utils::set_panic_hook;
|
||||||
|
|
@ -16,16 +18,14 @@ use std::convert::TryInto;
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::mem::take;
|
use std::mem::take;
|
||||||
use tf_demo_parser::demo::header::Header;
|
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::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::message::{Message, NetTickMessage};
|
||||||
use tf_demo_parser::demo::packet::message::{MessagePacket, MessagePacketMeta};
|
use tf_demo_parser::demo::packet::message::{MessagePacket, MessagePacketMeta};
|
||||||
use tf_demo_parser::demo::packet::stop::StopPacket;
|
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::packet::{Packet, PacketType};
|
||||||
use tf_demo_parser::demo::parser::{DemoHandler, Encode, NullHandler, RawPacketStream};
|
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 wasm_bindgen::prelude::*;
|
||||||
use web_sys::console;
|
use web_sys::console;
|
||||||
|
|
||||||
|
|
@ -282,3 +282,10 @@ fn net_tick(tick: u32) -> Message<'static> {
|
||||||
std_dev: 263,
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue