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", "client.dll",
signature!("48 8B 15 ? ? ? ? 48 85 D2 74 ? 0F 1F 40"), 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)?; 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 { let sig = match env::consts::OS {
"linux" => signature!("48 8B 1D ? ? ? ? 48 85 DB 74 ? 49 89 FC"), "linux" => signature!("48 8B 1D ? ? ? ? 48 85 DB 74 ? 49 89 FC"),
"windows" => signature!("4C 8B 0D ? ? ? ? 4C 8B D2 4C 8B D9"), "windows" => signature!("4C 8B 0D ? ? ? ? 4C 8B D2 4C 8B D9"),
_ => panic!("unsupported os"), os => panic!("unsupported os: {}", os),
}; };
process process

View File

@ -16,14 +16,14 @@ use crate::source_engine::*;
pub type SchemaMap = BTreeMap<String, (Vec<Class>, Vec<Enum>)>; 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 { pub enum ClassMetadata {
Unknown { name: String }, Unknown { name: String },
NetworkChangeCallback { name: String }, NetworkChangeCallback { name: String },
NetworkVarNames { name: String, ty: String }, NetworkVarNames { name: String, ty: String },
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Class { pub struct Class {
pub name: String, pub name: String,
pub module_name: String, pub module_name: String,
@ -32,14 +32,14 @@ pub struct Class {
pub fields: Vec<ClassField>, pub fields: Vec<ClassField>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ClassField { pub struct ClassField {
pub name: String, pub name: String,
pub ty: String, pub ty: String,
pub offset: u32, pub offset: u32,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Enum { pub struct Enum {
pub name: String, pub name: String,
pub ty: String, pub ty: String,
@ -48,7 +48,7 @@ pub struct Enum {
pub members: Vec<EnumMember>, pub members: Vec<EnumMember>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EnumMember { pub struct EnumMember {
pub name: String, pub name: String,
pub value: i64, pub value: i64,
@ -81,9 +81,9 @@ fn read_class_binding(
let module_name = binding.module_name.read_string(process).map(|s| { let module_name = binding.module_name.read_string(process).map(|s| {
let file_ext = match env::consts::OS { let file_ext = match env::consts::OS {
"linux" => "so", "linux" => ".so",
"windows" => "dll", "windows" => ".dll",
_ => panic!("unsupported os"), os => panic!("unsupported os: {}", os),
}; };
format!("{}.{}", s, file_ext) format!("{}.{}", s, file_ext)
@ -269,7 +269,7 @@ fn read_schema_system(process: &mut IntoProcessInstanceArcBox<'_>) -> Result<Sch
"schemasystem.dll", "schemasystem.dll",
signature!("48 89 05 ? ? ? ? 4C 8D 45"), signature!("48 89 05 ? ? ? ? 4C 8D 45"),
), ),
_ => panic!("unsupported os"), os => panic!("unsupported os: {}", os),
}; };
let module = process.module_by_name(&module_name)?; 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 { let file_name = match env::consts::OS {
"linux" => "config_linux.json", "linux" => "config_linux.json",
"windows" => "config_win.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"); 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 { .unwrap_or_else(|| match env::consts::OS {
"linux" => "linux".to_string(), "linux" => "linux".to_string(),
"windows" => "win32".to_string(), "windows" => "win32".to_string(),
_ => panic!("unsupported os"), os => panic!("unsupported os: {}", os),
}); });
let indent_size = *matches.get_one::<usize>("indent-size").unwrap(); 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> { impl CodeGen for Vec<Button> {
fn to_cs(&self, results: &Results, indent_size: usize) -> Result<String> { fn to_cs(&self, results: &Results, indent_size: usize) -> Result<String> {
self.write_content(results, indent_size, |fmt| { self.write_content(results, indent_size, |fmt| {
fmt.block("namespace CS2Dumper", |fmt| { fmt.block("namespace CS2Dumper", false, |fmt| {
writeln!(fmt, "// Module: {}", get_module_name())?; 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 { for button in self {
writeln!( writeln!(
fmt, fmt,
@ -34,10 +34,10 @@ impl CodeGen for Vec<Button> {
writeln!(fmt, "#pragma once\n")?; writeln!(fmt, "#pragma once\n")?;
writeln!(fmt, "#include <cstddef>\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())?; writeln!(fmt, "// Module: {}", get_module_name())?;
fmt.block("namespace buttons", |fmt| { fmt.block("namespace buttons", false, |fmt| {
for button in self { for button in self {
writeln!( writeln!(
fmt, fmt,
@ -71,10 +71,10 @@ impl CodeGen for Vec<Button> {
self.write_content(results, indent_size, |fmt| { self.write_content(results, indent_size, |fmt| {
writeln!(fmt, "#![allow(non_upper_case_globals, unused)]\n")?; 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())?; writeln!(fmt, "// Module: {}", get_module_name())?;
fmt.block("pub mod buttons", |fmt| { fmt.block("pub mod buttons", false, |fmt| {
for button in self { for button in self {
writeln!( writeln!(
fmt, 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 where
F: FnOnce(&mut Self) -> fmt::Result, F: FnOnce(&mut Self) -> fmt::Result,
{ {
write!(self, "{} {{\n", heading)?; writeln!(self, "{} {{", heading)?;
self.indent(f)?; self.indent(f)?;
write!(self, "}}\n")?; writeln!(self, "{}", if semicolon { "};" } else { "}" })?;
Ok(()) Ok(())
} }
@ -48,10 +48,10 @@ impl<'a> Formatter<'a> {
} }
#[inline] #[inline]
#[rustfmt::skip]
fn push_indentation(&mut self) { fn push_indentation(&mut self) {
if self.indent_level > 0 { 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(); let mut lines = s.lines().peekable();
while let Some(line) = lines.next() { while let Some(line) = lines.next() {
// Add indentation before the line if necessary.
if self.out.ends_with('\n') && !line.is_empty() { if self.out.ends_with('\n') && !line.is_empty() {
self.push_indentation(); self.push_indentation();
} }

View File

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

View File

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

View File

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

View File

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