mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-04 02:24:12 +02:00
generate propname mapping
This commit is contained in:
parent
e78c1f8608
commit
5976b43d56
4 changed files with 134 additions and 4 deletions
|
|
@ -1,4 +1,6 @@
|
|||
use crate::gameevent::generate_game_events;
|
||||
use crate::propnames::generate_prop_names;
|
||||
use main_error::MainError;
|
||||
use prettyplease::unparse;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
|
|
@ -6,8 +8,9 @@ use syn::{parse2, File};
|
|||
use tf_demo_parser::Demo;
|
||||
|
||||
mod gameevent;
|
||||
mod propnames;
|
||||
|
||||
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||
fn main() -> std::result::Result<(), MainError> {
|
||||
better_panic::install();
|
||||
|
||||
let args: Vec<_> = env::args().collect();
|
||||
|
|
@ -18,7 +21,11 @@ fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
|||
let path = args[1].clone();
|
||||
let file = fs::read(path).expect("Unable to read file");
|
||||
let demo = Demo::new(&file);
|
||||
let tokens = generate_game_events(demo);
|
||||
let tokens = match args.get(2).map(|s| s.as_str()) {
|
||||
None | Some("events") => generate_game_events(demo),
|
||||
Some("props") => generate_prop_names(demo),
|
||||
_ => panic!("unsupported"),
|
||||
};
|
||||
let file = parse2::<File>(tokens)?;
|
||||
let code = unparse(&file);
|
||||
println!("{}", code);
|
||||
|
|
|
|||
99
codegen/src/propnames.rs
Normal file
99
codegen/src/propnames.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
use fnv::{FnvHashMap, FnvHashSet};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName, ServerClass};
|
||||
use tf_demo_parser::demo::parser::MessageHandler;
|
||||
use tf_demo_parser::demo::sendprop::{SendPropIdentifier, SendPropName};
|
||||
use tf_demo_parser::{Demo, DemoParser, MessageType, ParserState};
|
||||
|
||||
struct PropInfo {
|
||||
identifier: SendPropIdentifier,
|
||||
table_name: String,
|
||||
prop_name: String,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct PropAnalyzer {
|
||||
props: FnvHashSet<SendPropIdentifier>,
|
||||
prop_names: FnvHashMap<SendPropIdentifier, (SendTableName, SendPropName)>,
|
||||
}
|
||||
|
||||
impl MessageHandler for PropAnalyzer {
|
||||
type Output = Vec<PropInfo>;
|
||||
|
||||
fn does_handle(message_type: MessageType) -> bool {
|
||||
matches!(message_type, MessageType::PacketEntities)
|
||||
}
|
||||
|
||||
fn handle_message(&mut self, message: &Message, _tick: u32) {
|
||||
if let Message::PacketEntities(message) = message {
|
||||
for entity in &message.entities {
|
||||
for prop in &entity.props {
|
||||
self.props.insert(prop.identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_data_tables(
|
||||
&mut self,
|
||||
parse_tables: &[ParseSendTable],
|
||||
_server_classes: &[ServerClass],
|
||||
) {
|
||||
for table in parse_tables {
|
||||
for prop_def in &table.props {
|
||||
self.prop_names.insert(
|
||||
prop_def.identifier(),
|
||||
(table.name.clone(), prop_def.name.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn into_output(self, _state: &ParserState) -> Self::Output {
|
||||
let mut props: Vec<_> = self
|
||||
.prop_names
|
||||
.into_iter()
|
||||
.map(|(identifier, (table_name, prop_name))| PropInfo {
|
||||
identifier,
|
||||
table_name: table_name.to_string(),
|
||||
prop_name: prop_name.to_string(),
|
||||
})
|
||||
.collect();
|
||||
props.sort_by(|a, b| a.identifier.cmp(&b.identifier));
|
||||
props
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_prop_names(demo: Demo) -> TokenStream {
|
||||
let (_, props) = DemoParser::new_with_analyser(demo.get_stream(), PropAnalyzer::default())
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let imports = quote!(
|
||||
use tf_demo_parser::demo::packet::datatable::SendTableName;
|
||||
use tf_demo_parser::demo::sendprop::{SendPropIdentifier, SendPropName};
|
||||
);
|
||||
|
||||
let matches = props.into_iter().map(|prop| {
|
||||
let identifier: u64 = prop.identifier.into();
|
||||
let table_name = prop.table_name;
|
||||
let prop_name = prop.prop_name;
|
||||
quote! {
|
||||
#identifier => Some((#table_name, #prop_name))
|
||||
}
|
||||
});
|
||||
|
||||
quote!(
|
||||
#imports
|
||||
|
||||
pub fn get_prop_names(identifier: SendPropIdentifier) -> Option<(&'static str, &'static str)> {
|
||||
let identifier: u64 = identifier.into();
|
||||
match identifier {
|
||||
#(#matches,)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue