Revert to old method of generating schema files

This commit is contained in:
a2x 2024-03-30 07:10:29 +10:00
parent 42ecdf593a
commit acb0c73f00
14 changed files with 99 additions and 133 deletions

View File

@ -27,7 +27,7 @@ pub fn buttons(process: &mut IntoProcessInstanceArcBox<'_>) -> Result<Vec<Button
"client.dll",
signature!("48 8B 15 ? ? ? ? 48 85 D2 74 ? 0F 1F 40"),
),
_ => panic!("unsupported os"),
os => panic!("unsupported os: {}", os),
};
let module = process.module_by_name(&module_name)?;

View File

@ -24,7 +24,7 @@ pub fn interfaces(process: &mut IntoProcessInstanceArcBox<'_>) -> Result<Interfa
let sig = match env::consts::OS {
"linux" => signature!("48 8B 1D ? ? ? ? 48 85 DB 74 ? 49 89 FC"),
"windows" => signature!("4C 8B 0D ? ? ? ? 4C 8B D2 4C 8B D9"),
_ => panic!("unsupported os"),
os => panic!("unsupported os: {}", os),
};
process

View File

@ -16,14 +16,14 @@ use crate::source_engine::*;
pub type SchemaMap = BTreeMap<String, (Vec<Class>, Vec<Enum>)>;
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
pub enum ClassMetadata {
Unknown { name: String },
NetworkChangeCallback { name: String },
NetworkVarNames { name: String, ty: String },
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Class {
pub name: String,
pub module_name: String,
@ -32,14 +32,14 @@ pub struct Class {
pub fields: Vec<ClassField>,
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ClassField {
pub name: String,
pub ty: String,
pub offset: u32,
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Enum {
pub name: String,
pub ty: String,
@ -48,7 +48,7 @@ pub struct Enum {
pub members: Vec<EnumMember>,
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EnumMember {
pub name: String,
pub value: i64,
@ -81,9 +81,9 @@ fn read_class_binding(
let module_name = binding.module_name.read_string(process).map(|s| {
let file_ext = match env::consts::OS {
"linux" => "so",
"windows" => "dll",
_ => panic!("unsupported os"),
"linux" => ".so",
"windows" => ".dll",
os => panic!("unsupported os: {}", os),
};
format!("{}.{}", s, file_ext)
@ -269,7 +269,7 @@ fn read_schema_system(process: &mut IntoProcessInstanceArcBox<'_>) -> Result<Sch
"schemasystem.dll",
signature!("48 89 05 ? ? ? ? 4C 8D 45"),
),
_ => panic!("unsupported os"),
os => panic!("unsupported os: {}", os),
};
let module = process.module_by_name(&module_name)?;

View File

@ -8,7 +8,7 @@ pub static CONFIG: LazyLock<Config> = LazyLock::new(|| {
let file_name = match env::consts::OS {
"linux" => "config_linux.json",
"windows" => "config_win.json",
_ => panic!("unsupported os"),
os => panic!("unsupported os: {}", os),
};
let content = fs::read_to_string(file_name).expect("unable to read config file");

View File

@ -150,7 +150,7 @@ fn extract_args(
.unwrap_or_else(|| match env::consts::OS {
"linux" => "linux".to_string(),
"windows" => "win32".to_string(),
_ => panic!("unsupported os"),
os => panic!("unsupported os: {}", os),
});
let indent_size = *matches.get_one::<usize>("indent-size").unwrap();

View File

@ -9,10 +9,10 @@ use crate::error::Result;
impl CodeGen for Vec<Button> {
fn to_cs(&self, results: &Results, indent_size: usize) -> Result<String> {
self.write_content(results, indent_size, |fmt| {
fmt.block("namespace CS2Dumper", |fmt| {
fmt.block("namespace CS2Dumper", false, |fmt| {
writeln!(fmt, "// Module: {}", get_module_name())?;
fmt.block("public static class Buttons", |fmt| {
fmt.block("public static class Buttons", false, |fmt| {
for button in self {
writeln!(
fmt,
@ -34,10 +34,10 @@ impl CodeGen for Vec<Button> {
writeln!(fmt, "#pragma once\n")?;
writeln!(fmt, "#include <cstddef>\n")?;
fmt.block("namespace cs2_dumper", |fmt| {
fmt.block("namespace cs2_dumper", false, |fmt| {
writeln!(fmt, "// Module: {}", get_module_name())?;
fmt.block("namespace buttons", |fmt| {
fmt.block("namespace buttons", false, |fmt| {
for button in self {
writeln!(
fmt,
@ -71,10 +71,10 @@ impl CodeGen for Vec<Button> {
self.write_content(results, indent_size, |fmt| {
writeln!(fmt, "#![allow(non_upper_case_globals, unused)]\n")?;
fmt.block("pub mod cs2_dumper", |fmt| {
fmt.block("pub mod cs2_dumper", false, |fmt| {
writeln!(fmt, "// Module: {}", get_module_name())?;
fmt.block("pub mod buttons", |fmt| {
fmt.block("pub mod buttons", false, |fmt| {
for button in self {
writeln!(
fmt,

View File

@ -21,15 +21,15 @@ impl<'a> Formatter<'a> {
}
}
pub fn block<F>(&mut self, heading: &str, f: F) -> fmt::Result
pub fn block<F>(&mut self, heading: &str, semicolon: bool, f: F) -> fmt::Result
where
F: FnOnce(&mut Self) -> fmt::Result,
{
write!(self, "{} {{\n", heading)?;
writeln!(self, "{} {{", heading)?;
self.indent(f)?;
write!(self, "}}\n")?;
writeln!(self, "{}", if semicolon { "};" } else { "}" })?;
Ok(())
}
@ -48,10 +48,10 @@ impl<'a> Formatter<'a> {
}
#[inline]
#[rustfmt::skip]
fn push_indentation(&mut self) {
if self.indent_level > 0 {
self.out.push_str(&" ".repeat(self.indent_level * self.indent_size));
self.out
.push_str(&" ".repeat(self.indent_level * self.indent_size));
}
}
}
@ -61,7 +61,6 @@ impl<'a> Write for Formatter<'a> {
let mut lines = s.lines().peekable();
while let Some(line) = lines.next() {
// Add indentation before the line if necessary.
if self.out.ends_with('\n') && !line.is_empty() {
self.push_indentation();
}

View File

@ -10,7 +10,7 @@ use crate::error::Result;
impl CodeGen for InterfaceMap {
fn to_cs(&self, results: &Results, indent_size: usize) -> Result<String> {
self.write_content(results, indent_size, |fmt| {
fmt.block("namespace CS2Dumper.Interfaces", |fmt| {
fmt.block("namespace CS2Dumper.Interfaces", false, |fmt| {
for (module_name, ifaces) in self {
writeln!(fmt, "// Module: {}", module_name)?;
@ -19,6 +19,7 @@ impl CodeGen for InterfaceMap {
"public static class {}",
AsPascalCase(format_module_name(module_name))
),
false,
|fmt| {
for iface in ifaces {
writeln!(
@ -45,13 +46,14 @@ impl CodeGen for InterfaceMap {
writeln!(fmt, "#pragma once\n")?;
writeln!(fmt, "#include <cstddef>\n")?;
fmt.block("namespace cs2_dumper", |fmt| {
fmt.block("namespace interfaces", |fmt| {
fmt.block("namespace cs2_dumper", false, |fmt| {
fmt.block("namespace interfaces", false, |fmt| {
for (module_name, ifaces) in self {
writeln!(fmt, "// Module: {}", module_name)?;
fmt.block(
&format!("namespace {}", AsSnakeCase(format_module_name(module_name))),
false,
|fmt| {
for iface in ifaces {
writeln!(
@ -94,13 +96,14 @@ impl CodeGen for InterfaceMap {
self.write_content(results, indent_size, |fmt| {
writeln!(fmt, "#![allow(non_upper_case_globals, unused)]\n")?;
fmt.block("pub mod cs2_dumper", |fmt| {
fmt.block("pub mod interfaces", |fmt| {
fmt.block("pub mod cs2_dumper", false, |fmt| {
fmt.block("pub mod interfaces", false, |fmt| {
for (module_name, ifaces) in self {
writeln!(fmt, "// Module: {}", module_name)?;
fmt.block(
&format!("pub mod {}", AsSnakeCase(format_module_name(module_name))),
false,
|fmt| {
for iface in ifaces {
writeln!(

View File

@ -147,22 +147,23 @@ impl Results {
out_dir: P,
indent_size: usize,
) -> Result<()> {
// TODO: Make this user-configurable.
const FILE_EXTS: &[&str] = &["cs", "hpp", "json", "rs"];
let items = [
("buttons", Item::Buttons(&self.buttons)),
("interfaces", Item::Interfaces(&self.interfaces)),
("offsets", Item::Offsets(&self.offsets)),
("schemas", Item::Schemas(&self.schemas)),
];
// TODO: Make this user-configurable.
let file_exts = ["cs", "hpp", "json", "rs"];
self.dump_items(&items, out_dir.as_ref(), indent_size, FILE_EXTS)?;
for (file_name, item) in &items {
for ext in file_exts {
let content = item.generate(self, indent_size, ext)?;
for (module_name, (classes, enums)) in &self.schemas {
let schemas = [(module_name.clone(), (classes.clone(), enums.clone()))].into();
self.dump_file(out_dir.as_ref(), file_name, ext, &content)?;
}
let item = Item::Schemas(&schemas);
self.dump_item(&item, out_dir.as_ref(), indent_size, FILE_EXTS, module_name)?;
}
self.dump_info_file(process, out_dir)?;
@ -189,19 +190,48 @@ impl Results {
process: &mut IntoProcessInstanceArcBox<'_>,
out_dir: P,
) -> Result<()> {
let info = json!({
"timestamp": self.timestamp.to_rfc3339(),
"build_number": self.read_build_number(process).unwrap_or(0),
});
self.dump_file(
out_dir.as_ref(),
"info",
"json",
&serde_json::to_string_pretty(&info)?,
&serde_json::to_string_pretty(&json!({
"timestamp": self.timestamp.to_rfc3339(),
"build_number": self.read_build_number(process).unwrap_or(0),
}))?,
)
}
fn dump_item<P: AsRef<Path>>(
&self,
item: &Item,
out_dir: P,
indent_size: usize,
file_exts: &[&str],
file_name: &str,
) -> Result<()> {
for ext in file_exts {
let content = item.generate(self, indent_size, ext)?;
self.dump_file(out_dir.as_ref(), file_name, ext, &content)?;
}
Ok(())
}
fn dump_items<P: AsRef<Path>>(
&self,
items: &[(&str, Item)],
out_dir: P,
indent_size: usize,
file_exts: &[&str],
) -> Result<()> {
for (file_name, item) in items {
self.dump_item(item, out_dir.as_ref(), indent_size, file_exts, file_name)?;
}
Ok(())
}
fn read_build_number(&self, process: &mut IntoProcessInstanceArcBox<'_>) -> Result<u32> {
self.offsets
.iter()
@ -230,7 +260,7 @@ pub fn format_module_name(module_name: &String) -> String {
let file_ext = match env::consts::OS {
"linux" => ".so",
"windows" => ".dll",
_ => panic!("unsupported os"),
os => panic!("unsupported os: {}", os),
};
module_name.strip_suffix(file_ext).unwrap().to_string()

View File

@ -10,7 +10,7 @@ use crate::error::Result;
impl CodeGen for OffsetMap {
fn to_cs(&self, results: &Results, indent_size: usize) -> Result<String> {
self.write_content(results, indent_size, |fmt| {
fmt.block("namespace CS2Dumper.Offsets", |fmt| {
fmt.block("namespace CS2Dumper.Offsets", false, |fmt| {
for (module_name, offsets) in self {
writeln!(fmt, "// Module: {}", module_name)?;
@ -19,6 +19,7 @@ impl CodeGen for OffsetMap {
"public static class {}",
AsPascalCase(format_module_name(module_name))
),
false,
|fmt| {
for offset in offsets {
writeln!(
@ -45,13 +46,14 @@ impl CodeGen for OffsetMap {
writeln!(fmt, "#pragma once\n")?;
writeln!(fmt, "#include <cstddef>\n")?;
fmt.block("namespace cs2_dumper", |fmt| {
fmt.block("namespace offsets", |fmt| {
fmt.block("namespace cs2_dumper", false, |fmt| {
fmt.block("namespace offsets", false, |fmt| {
for (module_name, offsets) in self {
writeln!(fmt, "// Module: {}", module_name)?;
fmt.block(
&format!("namespace {}", AsSnakeCase(format_module_name(module_name))),
false,
|fmt| {
for offset in offsets {
writeln!(
@ -94,13 +96,14 @@ impl CodeGen for OffsetMap {
self.write_content(results, indent_size, |fmt| {
writeln!(fmt, "#![allow(non_upper_case_globals, unused)]\n")?;
fmt.block("pub mod cs2_dumper", |fmt| {
fmt.block("pub mod offsets", |fmt| {
fmt.block("pub mod cs2_dumper", false, |fmt| {
fmt.block("pub mod offsets", false, |fmt| {
for (module_name, offsets) in self {
writeln!(fmt, "// Module: {}", module_name)?;
fmt.block(
&format!("pub mod {}", AsSnakeCase(format_module_name(module_name))),
false,
|fmt| {
for offset in offsets {
writeln!(

View File

@ -13,7 +13,7 @@ use crate::error::Result;
impl CodeGen for SchemaMap {
fn to_cs(&self, results: &Results, indent_size: usize) -> Result<String> {
self.write_content(results, indent_size, |fmt| {
fmt.block("namespace CS2Dumper.Schemas", |fmt| {
fmt.block("namespace CS2Dumper.Schemas", false, |fmt| {
for (module_name, (classes, enums)) in self {
writeln!(fmt, "// Module: {}", module_name)?;
writeln!(fmt, "// Classes count: {}", classes.len())?;
@ -24,6 +24,7 @@ impl CodeGen for SchemaMap {
"public static class {}",
AsPascalCase(format_module_name(module_name))
),
false,
|fmt| {
for enum_ in enums {
let ty = match enum_.ty.as_str() {
@ -39,6 +40,7 @@ impl CodeGen for SchemaMap {
fmt.block(
&format!("public enum {} : {}", sanitize_name(&enum_.name), ty),
false,
|fmt| {
let members = enum_
.members
@ -70,6 +72,7 @@ impl CodeGen for SchemaMap {
fmt.block(
&format!("public static class {}", sanitize_name(&class.name)),
false,
|fmt| {
for field in &class.fields {
writeln!(
@ -101,8 +104,8 @@ impl CodeGen for SchemaMap {
writeln!(fmt, "#pragma once\n")?;
writeln!(fmt, "#include <cstddef>\n")?;
fmt.block("namespace cs2_dumper", |fmt| {
fmt.block("namespace schemas", |fmt| {
fmt.block("namespace cs2_dumper", false, |fmt| {
fmt.block("namespace schemas", false, |fmt| {
for (module_name, (classes, enums)) in self {
writeln!(fmt, "// Module: {}", module_name)?;
writeln!(fmt, "// Classes count: {}", classes.len())?;
@ -110,6 +113,7 @@ impl CodeGen for SchemaMap {
fmt.block(
&format!("namespace {}", AsSnakeCase(format_module_name(module_name))),
false,
|fmt| {
for enum_ in enums {
let ty = match enum_.ty.as_str() {
@ -129,6 +133,7 @@ impl CodeGen for SchemaMap {
sanitize_name(&enum_.name),
ty
),
true,
|fmt| {
let members = enum_
.members
@ -160,6 +165,7 @@ impl CodeGen for SchemaMap {
fmt.block(
&format!("namespace {}", sanitize_name(&class.name)),
false,
|fmt| {
for field in &class.fields {
writeln!(
@ -270,8 +276,8 @@ impl CodeGen for SchemaMap {
self.write_content(results, indent_size, |fmt| {
writeln!(fmt, "#![allow(non_upper_case_globals, unused)]\n")?;
fmt.block("pub mod cs2_dumper", |fmt| {
fmt.block("pub mod schemas", |fmt| {
fmt.block("pub mod cs2_dumper", false, |fmt| {
fmt.block("pub mod schemas", false, |fmt| {
for (module_name, (classes, enums)) in self {
writeln!(fmt, "// Module: {}", module_name)?;
writeln!(fmt, "// Classes count: {}", classes.len())?;
@ -279,6 +285,7 @@ impl CodeGen for SchemaMap {
fmt.block(
&format!("pub mod {}", AsSnakeCase(format_module_name(module_name))),
false,
|fmt| {
for enum_ in enums {
let ty = match enum_.ty.as_str() {
@ -298,6 +305,7 @@ impl CodeGen for SchemaMap {
ty,
sanitize_name(&enum_.name),
),
false,
|fmt| {
// TODO: Handle the case where multiple members share
// the same value.
@ -331,6 +339,7 @@ impl CodeGen for SchemaMap {
fmt.block(
&format!("pub mod {}", sanitize_name(&class.name)),
false,
|fmt| {
for field in &class.fields {
writeln!(

View File

@ -1,44 +0,0 @@
use memflow::prelude::v1::*;
use super::UtlMemory;
use crate::error::Result;
#[repr(C)]
pub struct ConCommandBase {
pub name: Pointer64<ReprCString>,
pub description: Pointer64<ReprCString>,
pub flags: u64,
pad_0018: [u8; 0x20],
}
unsafe impl Pod for ConCommandBase {}
#[repr(C)]
pub struct CVar {
pad_0000: [u8; 0xD8],
pub cmds: UtlMemory<ConCommandBase>,
}
impl CVar {
pub fn iter(
&self,
process: &mut IntoProcessInstanceArcBox<'_>,
) -> Result<impl Iterator<Item = ConCommandBase>> {
let mut cmds = Vec::new();
for i in 0..self.cmds.alloc_count as usize {
let cmd = self.cmds.get(process, i)?;
if cmd.name.is_null() {
continue;
}
cmds.push(cmd);
}
Ok(cmds.into_iter())
}
}
unsafe impl Pod for CVar {}

View File

@ -1,11 +1,7 @@
pub use convar::*;
pub use interface::*;
pub use utl_memory::*;
pub use utl_ts_hash::*;
pub use utl_vector::*;
pub mod convar;
pub mod interface;
pub mod utl_memory;
pub mod utl_ts_hash;
pub mod utl_vector;

View File

@ -1,30 +0,0 @@
use std::mem;
use memflow::prelude::v1::*;
use crate::error::{Error, Result};
#[repr(C)]
pub struct UtlMemory<T: Sized + Pod> {
pub mem: Pointer64<T>,
pub alloc_count: u32,
pub grow_size: u32,
}
impl<T: Sized + Pod> UtlMemory<T> {
#[inline]
pub fn get(&self, process: &mut IntoProcessInstanceArcBox<'_>, idx: usize) -> Result<T> {
if idx >= self.alloc_count as usize {
return Err(Error::IndexOutOfBounds {
idx,
len: self.alloc_count as usize,
});
}
let ptr = Pointer64::from(self.mem.address() + (idx * mem::size_of::<T>()));
Ok(ptr.read(process)?)
}
}
unsafe impl<T: Sized + Pod> Pod for UtlMemory<T> {}