@@ -3,13 +3,20 @@ extends EditorExportPlugin
3
3
const REQUIRE_EXPLICIT_ADDITION := false
4
4
const METHOD_PREFIX := "vanilla_"
5
5
const HASH_COLLISION_ERROR := "MODDING EXPORT ERROR: Hash collision between %s and %s . The collision can be resolved by renaming one of the methods or changing their scripts path."
6
+
7
+ static var regex_getter_setter : RegEx
8
+
6
9
var hashmap := {}
7
10
11
+
8
12
func _get_name () -> String :
9
13
return "Godot Mod Loader Export Plugin"
10
14
11
15
func _export_begin (features : PackedStringArray , is_debug : bool , path : String , flags : int ) -> void :
12
16
hashmap .clear ()
17
+ regex_getter_setter = RegEx .new ()
18
+ regex_getter_setter .compile ("(.*?[sg]et\\ s*=\\ s*)(\\ w+)(\\ g<1>)?(\\ g<2>)?" )
19
+
13
20
14
21
func _export_file (path : String , type : String , features : PackedStringArray ) -> void :
15
22
if path .begins_with ("res://addons" ) or path .begins_with ("res://mods-unpacked" ):
@@ -22,7 +29,7 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
22
29
var source_code := current_script .source_code
23
30
var source_code_additions := ""
24
31
25
- # we need to stop all vanilla methods from forming inheritance chains
32
+ # we need to stop all vanilla methods from forming inheritance chains
26
33
# since the generated methods will fulfill inheritance requirements
27
34
var class_prefix = str (hash (path ))
28
35
var method_store : Array [String ] = []
@@ -37,20 +44,26 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
37
44
# print("-------------------- Method List")
38
45
# print(JSON.stringify(current_script.get_script_method_list(), "\t"))
39
46
# print("--------------------")
47
+ # print(path.get_file())
48
+ var getters_setters := collect_getters_and_setters (source_code )
49
+
40
50
for method in current_script .get_script_method_list ():
41
51
var method_first_line_start := get_index_at_method_start (method .name , source_code )
42
52
if method_first_line_start == - 1 or method .name in method_store :
43
53
continue
44
-
45
- if not is_func_moddable (method .name , method_first_line_start , source_code ):
54
+
55
+ if getters_setters .has (method .name ):
56
+ continue
57
+
58
+ if not is_func_moddable (method_first_line_start , source_code ):
46
59
continue
47
-
60
+
48
61
# print(method.flags)
49
62
var type_string := get_return_type_string (method .return )
50
63
var is_static := true if method .flags == METHOD_FLAG_STATIC + METHOD_FLAG_NORMAL else false
51
64
var method_arg_string_with_defaults_and_types := get_function_parameters (method .name , source_code , is_static )
52
65
var method_arg_string_names_only := get_function_arg_name_string (method .args )
53
-
66
+
54
67
var hash_before = ModLoaderMod .get_hook_hash (path , method .name , true )
55
68
var hash_after = ModLoaderMod .get_hook_hash (path , method .name , false )
56
69
var hash_before_data = [path , method .name ,true ]
@@ -61,7 +74,7 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
61
74
push_error (HASH_COLLISION_ERROR % [hashmap [hash_after ], hash_after_data ])
62
75
hashmap [hash_before ] = hash_before_data
63
76
hashmap [hash_after ] = hash_after_data
64
-
77
+
65
78
var mod_loader_hook_string := get_mod_loader_hook (
66
79
method .name ,
67
80
method_arg_string_names_only ,
@@ -83,11 +96,11 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
83
96
method_store .push_back (method .name )
84
97
source_code = prefix_method_name (method .name , is_static , source_code , METHOD_PREFIX + class_prefix )
85
98
source_code_additions += "\n %s " % mod_loader_hook_string
86
-
99
+
87
100
# if we have some additions to the code, append them at the end
88
101
if source_code_additions != "" :
89
102
source_code = "%s \n %s \n %s " % [source_code ,mod_loader_hooks_start_string , source_code_additions ]
90
-
103
+
91
104
skip ()
92
105
add_file (path , source_code .to_utf8_buffer (), false )
93
106
@@ -112,7 +125,7 @@ static func get_function_arg_name_string(args: Array) -> String:
112
125
arg_string += args [x ].name
113
126
else :
114
127
arg_string += "%s , " % args [x ].name
115
-
128
+
116
129
return arg_string
117
130
118
131
@@ -198,7 +211,7 @@ static func get_mod_loader_hook(
198
211
var self_string := "null" if is_static else "self"
199
212
var return_var := "var %s = " % "return_var" if not method_type .is_empty () or return_prop_usage == 131072 else ""
200
213
var method_return := "return %s " % "return_var" if not method_type .is_empty () or return_prop_usage == 131072 else ""
201
-
214
+
202
215
return """
203
216
{%STATIC%}func {%METHOD_NAME%}({%METHOD_PARAMS%}){%RETURN_TYPE_STRING%}:
204
217
ModLoaderMod.call_hooks({%SELF%}, [{%METHOD_ARGS%}], {%HOOK_ID_BEFORE%})
@@ -231,7 +244,7 @@ static func get_previous_line_to(text: String, index: int) -> String:
231
244
232
245
if start_index == 0 :
233
246
return ""
234
-
247
+
235
248
start_index -= 1
236
249
237
250
# Find the start of the previous line
@@ -241,9 +254,7 @@ static func get_previous_line_to(text: String, index: int) -> String:
241
254
242
255
return text .substr (start_index , end_index - start_index + 1 )
243
256
244
- static func is_func_moddable (method_name , method_start_idx , text ) -> bool :
245
- if is_setter (method_name , text ) or is_getter (method_name ,text ):
246
- return false
257
+ static func is_func_moddable (method_start_idx , text ) -> bool :
247
258
if not REQUIRE_EXPLICIT_ADDITION :
248
259
return true
249
260
return get_previous_line_to (text , method_start_idx ).contains ("@moddable" )
@@ -280,47 +291,27 @@ static func get_return_type_string(return_data: Dictionary) -> String:
280
291
return ""
281
292
var type_base
282
293
if return_data .has ("class_name" ) and not str (return_data .class_name ).is_empty ():
283
- type_base = str (return_data .class_name )
294
+ type_base = str (return_data .class_name )
284
295
else :
285
296
type_base = type_string (return_data .type )
286
-
297
+
287
298
var type_hint = "" if return_data .hint_string .is_empty () else ("[%s ]" % return_data .hint_string )
288
299
289
300
return "%s%s " % [type_base , type_hint ]
290
301
291
- static func is_setter (method_name : String , text : String , offset := 0 ) -> bool :
292
- var pattern := "set\\ s*=\\ s*%s " % method_name
293
- var regex := RegEx .new ()
294
- regex .compile (pattern )
295
302
296
- var result := regex .search (text , offset )
297
-
298
- if result :
299
- var line_start_index := text .rfind ("\n " , result .get_start ()) + 1
300
- var line_start_string := text .substr (result .get_start (), result .get_start () - line_start_index )
301
- if line_start_string .contains ("#" ):
302
-
303
- return is_setter (method_name , text , result .get_end ())
304
-
305
- return true
306
-
307
- return false
308
-
309
-
310
- static func is_getter (method_name : String , text : String , offset := 0 ) -> bool :
311
- var pattern := "get\\ s*=\\ s*%s " % method_name
312
- var regex := RegEx .new ()
313
- regex .compile (pattern )
314
-
315
- var result := regex .search (text , offset )
316
-
317
- if result :
318
- var line_start_index := text .rfind ("\n " , result .get_start ()) + 1
319
- var line_start_string := text .substr (result .get_start (), result .get_start () - line_start_index )
320
- if line_start_string .contains ("#" ):
321
-
322
- return is_setter (method_name , text , result .get_end ())
303
+ static func collect_getters_and_setters (text : String ) -> Dictionary :
304
+ var result := {}
305
+ # a valid match has 2 or 4 groups, split into the method names and the rest of the line
306
+ # (var example: set = )(example_setter)(, get = )(example_getter)
307
+ # if things between the names are empty or commented, exclude them
308
+ for mat in regex_getter_setter .search_all (text ):
309
+ if mat .get_string (1 ).is_empty () or mat .get_string (1 ).contains ("#" ):
310
+ continue
311
+ result [mat .get_string (2 )] = null
323
312
324
- return true
313
+ if mat .get_string (3 ).is_empty () or mat .get_string (3 ).contains ("#" ):
314
+ continue
315
+ result [mat .get_string (4 )] = null
325
316
326
- return false
317
+ return result
0 commit comments