Switch to custom demo parser

This commit is contained in:
Lol3rrr
2024-09-15 23:18:43 +02:00
parent 0ce8da7286
commit 44020a408f
5 changed files with 153 additions and 241 deletions

View File

@@ -17,62 +17,44 @@ pub struct BaseInfo {
pub fn analyse_base(input: AnalysisInput) -> BaseInfo {
tracing::info!("Performing Base analysis");
let huf = l_demoparser::second_pass::parser_settings::create_huffman_lookup_table();
let settings = l_demoparser::first_pass::parser_settings::ParserInputs {
wanted_players: Vec::new(),
real_name_to_og_name: ahash::AHashMap::default(),
wanted_player_props: vec!["X".to_string(), "team_num".to_string()],
wanted_events: vec!["player_death".to_string(), "player_team".to_string(), "team_info".to_string(), "player_spawn".to_string(), "team_score".to_string(), "round_end".to_string(), "game_end".to_string(), "match_end_conditions".to_string(), "switch_team".to_string(), "player_given_c4".to_string()],
wanted_other_props: vec![],
parse_ents: true,
wanted_ticks: Vec::new(),
parse_projectiles: false,
only_header: false,
count_props: false,
only_convars: false,
huffman_lookup_table: &huf,
order_by_steamid: false,
};
let mut ds = l_demoparser::parse_demo::Parser::new(settings, l_demoparser::parse_demo::ParsingMode::ForceSingleThreaded);
let file = std::fs::File::open(&input.path).unwrap();
let mmap = unsafe { memmap2::MmapOptions::new().map(&file).unwrap() };
let output = ds.parse_demo(&mmap).unwrap();
let header = output.header.as_ref().unwrap();
let tmp = csdemo::Container::parse(&mmap).unwrap();
let output = csdemo::parser::parse(csdemo::FrameIterator::parse(tmp.inner)).unwrap();
let header = &output.header;
tracing::info!("Header: {:?}", header);
for event in output.game_events.iter() {
match event.name.as_str() {
"player_team" => {
let team = event.fields.iter().find_map(|f| match (f.name.as_str(), &f.data) {
("team", Some(d)) => Some(d),
("team", None) => {
tracing::warn!("'team' field without data");
None
}
_ => None,
});
let user_name = event.fields.iter().find_map(|f| match (f.name.as_str(), &f.data) {
("user_name", Some(d)) => Some(d),
("user_name", None) => {
tracing::warn!("'user_name' field without data");
None
}
_ => None,
});
let steamid = event.fields.iter().find_map(|f| match (f.name.as_str(), &f.data) {
("user_steamid", Some(d)) => Some(d),
("user_steamid", None) => {
tracing::warn!("'user_steamid' field without data");
None
}
_ => None,
});
dbg!(&output.player_info);
tracing::info!("'{:?}' ({:?}) -> {:?}", user_name, steamid, team);
for event in output.events.iter() {
match event {
csdemo::DemoEvent::Tick(tick) => {}
csdemo::DemoEvent::ServerInfo(info) => {}
csdemo::DemoEvent::RankUpdate(update) => {}
csdemo::DemoEvent::RankReveal(reveal) => {}
csdemo::DemoEvent::GameEvent(gevent) => {
match gevent {
csdemo::game_event::GameEvent::PlayerTeam(pteam) => {
tracing::info!("{:?}", pteam);
}
csdemo::game_event::GameEvent::RoundOfficiallyEnded(r_end) => {
tracing::info!("{:?}", r_end);
}
csdemo::game_event::GameEvent::PlayerDeath(pdeath) => {
tracing::info!("{:?}", pdeath);
}
other => {}
};
}
};
/*
match event.name.as_str() {
"team_info" => {
tracing::info!("Team Info: {:?}", event);
}
@@ -82,34 +64,6 @@ pub fn analyse_base(input: AnalysisInput) -> BaseInfo {
"team_score" => {
tracing::info!("Team Score: {:?}", event);
}
"round_end" => {
let winner = event.fields.iter().find_map(|f| match (f.name.as_str(), &f.data) {
("winner", Some(d)) => Some(d),
("winner", None) => {
tracing::warn!("'winner' field without data");
None
}
_ => None,
});
let round = event.fields.iter().find_map(|f| match (f.name.as_str(), &f.data) {
("round", Some(d)) => Some(d),
("round", None) => {
tracing::warn!("'round' field without data");
None
}
_ => None,
});
let reason = event.fields.iter().find_map(|f| match (f.name.as_str(), &f.data) {
("reason", Some(d)) => Some(d),
("reason", None) => {
tracing::warn!("'reason' field without data");
None
}
_ => None,
});
tracing::info!(?winner, ?round, ?reason, "Round End");
}
"game_end" => {
tracing::info!("Game End: {:?}", event);
}
@@ -124,10 +78,13 @@ pub fn analyse_base(input: AnalysisInput) -> BaseInfo {
}
_ => {}
};
*/
}
let map = header.map_name().to_owned();
BaseInfo {
map: header.get("map_name").cloned().unwrap_or_default(),
map,
players: Vec::new()
}
}

View File

@@ -14,6 +14,7 @@ use crate::UserSession;
.route("/list", axum::routing::get(list))
.route("/upload", axum::routing::post(upload).layer(axum::extract::DefaultBodyLimit::max(500*1024*1024)))
.route("/:id/info", axum::routing::get(info))
.route("/:id/reanalyse", axum::routing::get(analyise))
.with_state(Arc::new(DemoState {
upload_folder: upload_folder.into(),
base_analysis,
@@ -75,6 +76,31 @@ use crate::UserSession;
Ok(axum::response::Redirect::to("/"))
}
#[tracing::instrument(skip(state, session))]
async fn analyise(State(state): State<Arc<DemoState>>, session: crate::UserSession, Path(demo_id): Path<i64>) -> Result<(), (axum::http::StatusCode, &'static str)> {
let steam_id = session.data().steam_id.ok_or_else(|| (axum::http::StatusCode::UNAUTHORIZED, "Not logged in"))?;
tracing::info!("Upload for Session: {:?}", steam_id);
let mut db_con = crate::db_connection().await;
let query = crate::schema::demos::dsl::demos.filter(crate::schema::demos::dsl::steam_id.eq(steam_id.to_string())).filter(crate::schema::demos::dsl::demo_id.eq(demo_id));
let result: Vec<_> = query.load::<crate::models::Demo>(&mut db_con).await.unwrap();
if result.len() != 1 {
return Err((axum::http::StatusCode::BAD_REQUEST, "Expected exactly 1 demo to match"));
}
let user_folder = std::path::Path::new(&state.upload_folder).join(format!("{}/", steam_id));
state.base_analysis.send(crate::analysis::AnalysisInput {
path: user_folder.join(format!("{}.dem", demo_id)),
demoid: demo_id,
steamid: steam_id.to_string(),
});
Ok(())
}
#[tracing::instrument(skip(session))]
async fn info(session: UserSession, Path(demo_id): Path<i64>) -> Result<axum::response::Json<common::DemoInfo>, axum::http::StatusCode> {
tracing::info!("Get info for Demo: {:?}", demo_id);

View File

@@ -28,6 +28,8 @@ async fn main() {
let (base_analysis_tx, mut base_analysis_rx) = tokio::sync::mpsc::unbounded_channel::<backend::analysis::AnalysisInput>();
tokio::task::spawn_blocking(move || {
use diesel_async::AsyncConnection;
while let Some(input) = base_analysis_rx.blocking_recv() {
let demo_id = input.demoid;
let result = backend::analysis::analyse_base(input);
@@ -47,8 +49,11 @@ async fn main() {
tracing::trace!(?store_info_query, "Store demo info query");
tracing::trace!(?update_process_info, "Update processing info query");
store_info_query.execute(&mut db_con).await.unwrap();
update_process_info.execute(&mut db_con).await.unwrap();
db_con.transaction::<'_, '_, '_, _, diesel::result::Error, _>(|conn| Box::pin(async move {
store_info_query.execute(conn).await.map(|e| ())?;
update_process_info.execute(conn).await.map(|e| ())?;
Ok(())
})).await;
}
);
}