Skip to content

Commit 57b92f1

Browse files
committed
feat: 🚧 fixed issues with inheritance by adding class hash
added getter method, made both static and moved getter/setter check to is_moddable check
1 parent bad077b commit 57b92f1

File tree

1 file changed

+44
-24
lines changed

1 file changed

+44
-24
lines changed

addons/mod_loader/_export_plugin/export_plugin.gd

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
extends EditorExportPlugin
22

33
const REQUIRE_EXPLICIT_ADDITION := false
4-
const METHOD_PREFIX := "GodotModLoader"
5-
4+
const METHOD_PREFIX := "vanilla_"
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."
66
var hashmap := {}
77

88
func _get_name() -> String:
@@ -15,15 +15,17 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
1515
if path.begins_with("res://addons") or path.begins_with("res://mods-unpacked"):
1616
return
1717

18-
if not type == "GDScript":
18+
if type != "GDScript":
1919
return
2020

2121
var current_script := load(path) as GDScript
2222
var source_code := current_script.source_code
2323
var source_code_additions := ""
2424

25+
#we need to stop all vanilla methods from forming inheritance chains
26+
#since the generated methods will fulfill inheritance requirements
27+
var class_prefix = str(hash(path))
2528
var method_store: Array[String] = []
26-
2729
var mod_loader_hooks_start_string := """
2830
# ModLoader Hooks - The following code has been automatically added by the Godot Mod Loader export plugin.
2931
"""
@@ -39,13 +41,11 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
3941
var method_first_line_start := get_index_at_method_start(method.name, source_code)
4042
if method_first_line_start == -1 or method.name in method_store:
4143
continue
42-
43-
if not is_func_moddable(method_first_line_start, source_code):
44-
continue
45-
46-
if is_setter(method.name, source_code):
44+
45+
if not is_func_moddable(method.name, method_first_line_start, source_code):
4746
continue
48-
47+
48+
#print(method.flags)
4949
var type_string := get_return_type_string(method.return)
5050
var is_static := true if method.flags == METHOD_FLAG_STATIC + METHOD_FLAG_NORMAL else false
5151
var method_arg_string_with_defaults_and_types := get_function_parameters(method.name, source_code, is_static)
@@ -56,9 +56,9 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
5656
var hash_before_data = [path, method.name,true]
5757
var hash_after_data = [path, method.name,false]
5858
if hashmap.has(hash_before):
59-
push_error("MODDING EXPORT ERROR: hash collision between %s and %s." %[hashmap[hash_before], hash_before_data])
59+
push_error(HASH_COLLISION_ERROR%[hashmap[hash_before], hash_before_data])
6060
if hashmap.has(hash_after):
61-
push_error("MODDING EXPORT ERROR: hash collision between %s and %s." %[hashmap[hash_after], hash_after_data])
61+
push_error(HASH_COLLISION_ERROR %[hashmap[hash_after], hash_after_data])
6262
hashmap[hash_before] = hash_before_data
6363
hashmap[hash_after] = hash_after_data
6464

@@ -72,6 +72,7 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
7272
path,
7373
hash_before,
7474
hash_after,
75+
METHOD_PREFIX + class_prefix,
7576
)
7677

7778
# Store the method name
@@ -80,13 +81,13 @@ func _export_file(path: String, type: String, features: PackedStringArray) -> vo
8081
# including the methods from the scripts it extends,
8182
# which leads to multiple entries in the list if they are overridden by the child script.
8283
method_store.push_back(method.name)
83-
source_code = prefix_method_name(method.name, is_static, source_code)
84+
source_code = prefix_method_name(method.name, is_static, source_code, METHOD_PREFIX + class_prefix)
8485
source_code_additions += "\n%s" % mod_loader_hook_string
85-
86+
8687
#if we have some additions to the code, append them at the end
8788
if source_code_additions != "":
8889
source_code = "%s\n%s\n%s" % [source_code,mod_loader_hooks_start_string, source_code_additions]
89-
90+
9091
skip()
9192
add_file(path, source_code.to_utf8_buffer(), false)
9293

@@ -111,7 +112,7 @@ static func get_function_arg_name_string(args: Array) -> String:
111112
arg_string += args[x].name
112113
else:
113114
arg_string += "%s, " % args[x].name
114-
115+
115116
return arg_string
116117

117118

@@ -180,7 +181,6 @@ static func prefix_method_name(method_name: String, is_static: bool, text: Strin
180181
print("WHAT?!")
181182
return text
182183

183-
184184
static func get_mod_loader_hook(
185185
method_name: String,
186186
method_arg_string_names_only: String,
@@ -198,7 +198,7 @@ static func get_mod_loader_hook(
198198
var self_string := "null" if is_static else "self"
199199
var return_var := "var %s = " % "return_var" if not method_type.is_empty() or return_prop_usage == 131072 else ""
200200
var method_return := "return %s" % "return_var" if not method_type.is_empty() or return_prop_usage == 131072 else ""
201-
201+
202202
return """
203203
{%STATIC%}func {%METHOD_NAME%}({%METHOD_PARAMS%}){%RETURN_TYPE_STRING%}:
204204
ModLoaderMod.call_hooks({%SELF%}, [{%METHOD_ARGS%}], {%HOOK_ID_BEFORE%})
@@ -231,7 +231,7 @@ static func get_previous_line_to(text: String, index: int) -> String:
231231

232232
if start_index == 0:
233233
return ""
234-
234+
235235
start_index -= 1
236236

237237
# Find the start of the previous line
@@ -241,7 +241,9 @@ static func get_previous_line_to(text: String, index: int) -> String:
241241

242242
return text.substr(start_index, end_index - start_index + 1)
243243

244-
static func is_func_moddable(method_start_idx, text) -> bool:
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
245247
if not REQUIRE_EXPLICIT_ADDITION:
246248
return true
247249
return get_previous_line_to(text, method_start_idx).contains("@moddable")
@@ -278,16 +280,15 @@ static func get_return_type_string(return_data: Dictionary) -> String:
278280
return ""
279281
var type_base
280282
if return_data.has("class_name") and not str(return_data.class_name).is_empty():
281-
type_base = str(return_data.class_name)
283+
type_base = str(return_data.class_name)
282284
else:
283285
type_base = type_string(return_data.type)
284-
286+
285287
var type_hint = "" if return_data.hint_string.is_empty() else ("[%s]" % return_data.hint_string)
286288

287289
return "%s%s" % [type_base, type_hint]
288290

289-
290-
func is_setter(method_name: String, text: String, offset := 0) -> bool:
291+
static func is_setter(method_name: String, text: String, offset := 0) -> bool:
291292
var pattern := "set\\s*=\\s*%s" % method_name
292293
var regex := RegEx.new()
293294
regex.compile(pattern)
@@ -304,3 +305,22 @@ func is_setter(method_name: String, text: String, offset := 0) -> bool:
304305
return true
305306

306307
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())
323+
324+
return true
325+
326+
return false

0 commit comments

Comments
 (0)