Skip to content

Commit 0256a6d

Browse files
authored
0.4.2 (SB 4.2.0)
1 parent 77d3502 commit 0256a6d

File tree

11 files changed

+256
-12
lines changed

11 files changed

+256
-12
lines changed

Cargo.lock

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sanny_builder_core"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
authors = ["Seemann <mail@sannybuilder.com>"]
55
edition = "2021"
66

@@ -33,4 +33,5 @@ normpath = "1.2"
3333
lines_lossy = "0.1.0"
3434
zip = { git = "https://github.com/x87/zip.git" }
3535
const_format = "0.2.32"
36-
cached = "0.50.0"
36+
cached = "0.50.0"
37+
gta-ide-parser = "0.0.4"

src/ide/ffi.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use libc::c_char;
2+
3+
use super::model_list::ModelList;
4+
5+
use crate::common_ffi::*;
6+
7+
#[no_mangle]
8+
pub extern "C" fn model_list_new() -> *mut ModelList {
9+
ptr_new(ModelList::new())
10+
}
11+
12+
#[no_mangle]
13+
pub unsafe extern "C" fn model_list_free(list: *mut ModelList) {
14+
ptr_free(list)
15+
}
16+
17+
#[no_mangle]
18+
pub unsafe extern "C" fn model_list_load_from_file(list: *mut ModelList, file_name: PChar) -> bool {
19+
boolclosure!({
20+
list.as_mut()?.load_from_file(pchar_to_str(file_name)?);
21+
Some(())
22+
})
23+
}
24+
25+
#[no_mangle]
26+
pub unsafe extern "C" fn model_list_get_by_id(
27+
list: *mut ModelList,
28+
id: i32,
29+
out: *mut PChar,
30+
) -> bool {
31+
boolclosure!({
32+
*out = list.as_mut()?.find_by_id(id)?.as_ptr();
33+
Some(())
34+
})
35+
}
36+
37+
#[no_mangle]
38+
pub unsafe extern "C" fn model_list_get_by_name(
39+
list: *mut ModelList,
40+
name: PChar,
41+
out_id: *mut i32,
42+
out_type: *mut u8,
43+
) -> bool {
44+
boolclosure!({
45+
let name = pchar_to_str(name)?;
46+
let model = list.as_mut()?.find_by_name(&name)?;
47+
*out_id = model.id;
48+
*out_type = model.r#type as u8;
49+
Some(())
50+
})
51+
}
52+
53+
#[no_mangle]
54+
pub unsafe extern "C" fn model_list_filter_names(
55+
list: *mut ModelList,
56+
needle: PChar,
57+
dict: *mut crate::dictionary::dictionary_str_by_num::DictStrByNum,
58+
) -> bool {
59+
boolclosure!({
60+
let needle = pchar_to_str(needle)?;
61+
let results = list.as_mut()?.filter_by_name(&needle);
62+
for (name, id) in results {
63+
dict.as_mut()?.add(id, name);
64+
}
65+
Some(())
66+
})
67+
}

src/ide/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod model_list;
2+
pub mod ffi;

src/ide/model_list.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use ctor::ctor;
2+
use simplelog::*;
3+
use std::{
4+
collections::HashMap,
5+
ffi::{c_char, CString},
6+
path::Path,
7+
};
8+
9+
#[repr(C)]
10+
#[derive(Copy, Clone, PartialEq)]
11+
pub enum ModelType {
12+
Object,
13+
Vehicle,
14+
Ped,
15+
Weapon,
16+
Hier,
17+
}
18+
19+
#[repr(C)]
20+
pub struct Model {
21+
pub id: i32,
22+
pub r#type: ModelType,
23+
}
24+
25+
pub struct ModelList {
26+
pub _by_id: HashMap<i32, CString>,
27+
pub _by_name: HashMap<String, Model>,
28+
pub model_names: Vec<String>,
29+
}
30+
31+
impl ModelList {
32+
pub fn new() -> Self {
33+
Self {
34+
_by_id: HashMap::new(),
35+
_by_name: HashMap::new(),
36+
model_names: Vec::new(),
37+
}
38+
}
39+
40+
pub fn load_from_file(&mut self, file_name: &str) {
41+
let Ok(content) = std::fs::read_to_string(file_name) else {
42+
log::error!("Failed to read file: {}", file_name);
43+
return;
44+
};
45+
let Ok(ide) = gta_ide_parser::parse(&content) else {
46+
log::error!("Failed to parse IDE: {}", file_name);
47+
return;
48+
};
49+
for (section_name, lines) in ide {
50+
if ["txdp", "path", "2dfx"].contains(&section_name.as_str()) {
51+
continue;
52+
}
53+
for line in lines {
54+
let Ok(id) = line[0].parse::<i32>() else {
55+
log::error!("Failed to parse ID: {} in {}", line[0], file_name);
56+
continue;
57+
};
58+
let name = line[1].to_string();
59+
let r#type = match section_name.as_str() {
60+
"objs" | "tobj" | "anim" | "tanm" => ModelType::Object,
61+
"cars" => ModelType::Vehicle,
62+
"peds" => ModelType::Ped,
63+
"weap" => ModelType::Weapon,
64+
"hier" => ModelType::Hier,
65+
_ => {
66+
continue;
67+
}
68+
};
69+
70+
self.model_names.push(name.to_uppercase());
71+
self._by_id
72+
.insert(id, CString::new(name.to_uppercase()).unwrap());
73+
self._by_name
74+
.insert(name.to_ascii_lowercase(), Model { id, r#type });
75+
}
76+
}
77+
}
78+
79+
pub fn find_by_id(&self, id: i32) -> Option<&CString> {
80+
self._by_id.get(&id)
81+
}
82+
83+
pub fn find_by_name(&self, name: &str) -> Option<&Model> {
84+
let needle = &name.to_ascii_lowercase();
85+
match needle.as_str() {
86+
// old parser did not properly handle missing commas, resulting in broken names
87+
"emperoremperor" => {
88+
return Some(&Model {
89+
id: 585,
90+
r#type: ModelType::Vehicle,
91+
})
92+
}
93+
"wayfarerwayfarer" => {
94+
return Some(&Model {
95+
id: 586,
96+
r#type: ModelType::Vehicle,
97+
})
98+
}
99+
"dodododo" => {
100+
return Some(&Model {
101+
id: 593,
102+
r#type: ModelType::Vehicle,
103+
})
104+
}
105+
_ => self._by_name.get(needle),
106+
}
107+
}
108+
109+
pub fn filter_by_name(&self, needle: &str) -> Vec<(CString, i32)> {
110+
let needle = needle.to_ascii_uppercase();
111+
let mut results = Vec::new();
112+
for name in self.model_names.iter() {
113+
if name.contains(&needle) {
114+
if let Some(model) = self.find_by_name(name) {
115+
if model.r#type == ModelType::Object {
116+
continue; // Skip objects
117+
}
118+
results.push((CString::new(name.clone()).unwrap(), model.id));
119+
// if results.len() >= 200 {
120+
// break; // Limit results to 200
121+
// }
122+
}
123+
}
124+
}
125+
results
126+
}
127+
}

src/language_service/ffi.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ pub unsafe extern "C" fn language_service_format_function_signature(
181181
.map(|param|{
182182
let type_token = token_str(line, &param._type);
183183
let name_token = param.name.as_ref().map(|name| token_str(line, name));
184+
let size_token = param.size.as_ref().map(|size| token_str(line, size));
185+
186+
let type_token = if let Some(size) = size_token {
187+
format!("{}[{}]", type_token, size)
188+
} else {
189+
type_token.to_string()
190+
};
184191

185192
match name_token {
186193
Some(name) => format!("\"{}: {}\"", name, type_token),

src/language_service/scanner.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,13 +731,18 @@ fn function_params_and_return_types(line: &str, signature: &FunctionSignature) -
731731
.map(|param| {
732732
let type_token = token_str(line, &param._type);
733733
let name_token = param.name.as_ref().map(|name| token_str(line, name));
734+
let size_token = param.size.as_ref().map(|size| token_str(line, size));
734735

736+
let type_token = if let Some(size) = size_token {
737+
format!("{}[{}]", type_token, size)
738+
} else {
739+
type_token.to_string()
740+
};
735741
match name_token {
736742
Some(name) => format!("{}: {}", name, type_token),
737743
None => format!("{}", type_token),
738744
}
739745
})
740-
// .map(|param| [token_str(line, &param.name), token_str(line, &param._type)].join(": "))
741746
.collect::<Vec<String>>()
742747
.join(", ");
743748

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub mod v4;
1717
pub mod source_map;
1818
pub mod preprocessor;
1919
pub mod sanny_update;
20+
pub mod ide;
2021

2122
#[ctor]
2223
fn main() {
@@ -37,5 +38,5 @@ fn main() {
3738
std::fs::File::create(cwd.join("core.log")).unwrap(),
3839
);
3940

40-
log::info!("core library loaded");
41+
log::info!("core library {} loaded", env!("CARGO_PKG_VERSION"));
4142
}

src/namespaces/namespaces.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,18 @@ impl Namespaces {
150150
use crate::namespaces::enum_parser::{parse_enums, EnumItems};
151151

152152
let content = std::fs::read_to_string(file_name).ok()?;
153-
let (_, enums) = parse_enums(&content).ok()?;
153+
let enums = match parse_enums(&content) {
154+
Ok((rest, enums)) => {
155+
if !rest.is_empty() {
156+
log::warn!("Some enums could not be parsed: {rest} in file: {file_name}");
157+
}
158+
enums
159+
}
160+
Err(e) => {
161+
log::error!("Failed on parsing file {file_name}: {e}");
162+
return None;
163+
}
164+
};
154165
for e in enums {
155166
let mut members = HashMap::new();
156167
match e.items {

0 commit comments

Comments
 (0)