Skip to content

Commit c29ac0d

Browse files
KANAjetztAlexejheroQubus0
authored
refactor: ♻️ 4.1 support (#508)
* Remove type hint for for...in variable * Remove another typed for...in variable * Fix production_no_workshop.tres format * Fix production_workshop.tres format * Use custom function instead of type_string * keep type in `load_mods()` * refactor: ♻️ `fix_method_super()` use `erase` `insert` instead of `sub` _ModLoaderModHookPreProcessor.fix_method_super() erased everything after the function body, leaving only the first function in a script. * refactor: ♻️ remove inline type in for * style: 🔥 remove white space * refactor: ♻️ engine version check * fix: ✏️ fix typo * refactor: ♻️ engine_version as int * refactor: ♻️ use version hex and link to PR * fix: 🐛 fixed type * refactor: ♻️ use RegEx.sub() and add back text * Update addons/mod_loader/internal/mod_hook_preprocessor.gd * Update addons/mod_loader/internal/mod_hook_preprocessor.gd Co-authored-by: steen <steen.rickmer@gmx.de> --------- Co-authored-by: Alexejhero <32238504+Alexejhero@users.noreply.github.com> Co-authored-by: steen <steen.rickmer@gmx.de>
1 parent c11cc6a commit c29ac0d

File tree

3 files changed

+124
-12
lines changed

3 files changed

+124
-12
lines changed

addons/mod_loader/internal/mod_hook_preprocessor.gd

Lines changed: 116 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@tool
12
class_name _ModLoaderModHookPreProcessor
23
extends RefCounted
34

@@ -13,15 +14,18 @@ const HASH_COLLISION_ERROR := \
1314
"MODDING HOOKS ERROR: Hash collision between %s and %s. The collision can be resolved by renaming one of the methods or changing their script's path."
1415
const MOD_LOADER_HOOKS_START_STRING := \
1516
"\n# ModLoader Hooks - The following code has been automatically added by the Godot Mod Loader."
17+
const ENGINE_VERSION_HEX_4_2_2 := 0x040202
1618

1719
## \\bfunc\\b\\s+ -> Match the word 'func' and one or more whitespace characters
1820
## \\b%s\\b -> the function name
1921
## (?:.*\\n*)*?\\s*\\( -> Match any character between zero and unlimited times, but be lazy
2022
## and only do this until a '(' is found.
2123
const REGEX_MATCH_FUNC_WITH_WHITESPACE := "\\bfunc\\b\\s+\\b%s\\b(?:.*\\n*)*?\\s*\\("
2224

25+
static var engine_version_hex: int = Engine.get_version_info().hex
26+
2327
## finds function names used as setters and getters (excluding inline definitions)
24-
## group 2 and 4 contain the xetter names
28+
## group 2 and 4 contain the setter/getter names
2529
var regex_getter_setter := RegEx.create_from_string("(.*?[sg]et\\s*=\\s*)(\\w+)(\\g<1>)?(\\g<2>)?")
2630

2731
## finds every instance where super() is called
@@ -198,7 +202,8 @@ func is_func_async(func_body_text: String) -> bool:
198202
var in_multiline_string := false
199203
var current_multiline_delimiter := ""
200204

201-
for line: String in lines:
205+
for _line in lines:
206+
var line: String = _line
202207
var char_index := 0
203208
while char_index < line.length():
204209
if in_multiline_string:
@@ -327,13 +332,33 @@ func edit_vanilla_method(
327332
return text
328333

329334

330-
func fix_method_super(method_name: String, func_body: RegExMatch, text: String) -> String:
335+
func fix_method_super(method_name: String, func_body: RegExMatch, text: String) -> String:
336+
if engine_version_hex < ENGINE_VERSION_HEX_4_2_2:
337+
return fix_method_super_before_4_2_2(method_name, func_body, text)
338+
331339
return regex_super_call.sub(
332340
text, "super.%s" % method_name,
333341
true, func_body.get_start(), func_body.get_end()
334342
)
335343

336344

345+
# https://github.com/godotengine/godot/pull/86052
346+
# Quote:
347+
# When the end argument of RegEx.sub was used,
348+
# it would truncate the Subject String before even doing the substitution.
349+
func fix_method_super_before_4_2_2(method_name: String, func_body: RegExMatch, text: String) -> String:
350+
var text_after_func_body_end := text.substr(func_body.get_end())
351+
352+
text = regex_super_call.sub(
353+
text, "super.%s" % method_name,
354+
true, func_body.get_start(), func_body.get_end()
355+
)
356+
357+
text = text + text_after_func_body_end
358+
359+
return text
360+
361+
337362
static func get_func_body_start_index(closing_paren_index: int, source_code: String) -> int:
338363
if closing_paren_index == -1:
339364
return -1
@@ -495,7 +520,7 @@ static func get_return_type_string(return_data: Dictionary) -> String:
495520
if return_data.has("class_name") and not str(return_data.class_name).is_empty():
496521
type_base = str(return_data.class_name)
497522
else:
498-
type_base = type_string(return_data.type)
523+
type_base = get_type_name(return_data.type)
499524

500525
var type_hint: String = "" if return_data.hint_string.is_empty() else ("[%s]" % return_data.hint_string)
501526

@@ -535,3 +560,90 @@ static func get_hook_check_else_string(
535560
"METHOD_ARGS": method_arg_string_names_only
536561
}
537562
)
563+
564+
565+
# This function was taken from
566+
# https://github.com/godotengine/godot/blob/7e67b496ff7e35f66b88adcbdd5b252d01739cbb/modules/gdscript/tests/scripts/utils.notest.gd#L69
567+
# It is used instead of type_string because type_string does not exist in Godot 4.1
568+
static func get_type_name(type: Variant.Type) -> String:
569+
match type:
570+
TYPE_NIL:
571+
return "Nil" # `Nil` in core, `null` in GDScript.
572+
TYPE_BOOL:
573+
return "bool"
574+
TYPE_INT:
575+
return "int"
576+
TYPE_FLOAT:
577+
return "float"
578+
TYPE_STRING:
579+
return "String"
580+
TYPE_VECTOR2:
581+
return "Vector2"
582+
TYPE_VECTOR2I:
583+
return "Vector2i"
584+
TYPE_RECT2:
585+
return "Rect2"
586+
TYPE_RECT2I:
587+
return "Rect2i"
588+
TYPE_VECTOR3:
589+
return "Vector3"
590+
TYPE_VECTOR3I:
591+
return "Vector3i"
592+
TYPE_TRANSFORM2D:
593+
return "Transform2D"
594+
TYPE_VECTOR4:
595+
return "Vector4"
596+
TYPE_VECTOR4I:
597+
return "Vector4i"
598+
TYPE_PLANE:
599+
return "Plane"
600+
TYPE_QUATERNION:
601+
return "Quaternion"
602+
TYPE_AABB:
603+
return "AABB"
604+
TYPE_BASIS:
605+
return "Basis"
606+
TYPE_TRANSFORM3D:
607+
return "Transform3D"
608+
TYPE_PROJECTION:
609+
return "Projection"
610+
TYPE_COLOR:
611+
return "Color"
612+
TYPE_STRING_NAME:
613+
return "StringName"
614+
TYPE_NODE_PATH:
615+
return "NodePath"
616+
TYPE_RID:
617+
return "RID"
618+
TYPE_OBJECT:
619+
return "Object"
620+
TYPE_CALLABLE:
621+
return "Callable"
622+
TYPE_SIGNAL:
623+
return "Signal"
624+
TYPE_DICTIONARY:
625+
return "Dictionary"
626+
TYPE_ARRAY:
627+
return "Array"
628+
TYPE_PACKED_BYTE_ARRAY:
629+
return "PackedByteArray"
630+
TYPE_PACKED_INT32_ARRAY:
631+
return "PackedInt32Array"
632+
TYPE_PACKED_INT64_ARRAY:
633+
return "PackedInt64Array"
634+
TYPE_PACKED_FLOAT32_ARRAY:
635+
return "PackedFloat32Array"
636+
TYPE_PACKED_FLOAT64_ARRAY:
637+
return "PackedFloat64Array"
638+
TYPE_PACKED_STRING_ARRAY:
639+
return "PackedStringArray"
640+
TYPE_PACKED_VECTOR2_ARRAY:
641+
return "PackedVector2Array"
642+
TYPE_PACKED_VECTOR3_ARRAY:
643+
return "PackedVector3Array"
644+
TYPE_PACKED_COLOR_ARRAY:
645+
return "PackedColorArray"
646+
38: # TYPE_PACKED_VECTOR4_ARRAY
647+
return "PackedVector4Array"
648+
push_error("Argument `type` is invalid. Use `TYPE_*` constants.")
649+
return "<unknown type %s>" % type
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
[gd_resource type="Resource" script_class="ModLoaderOptionsProfile" load_steps=2 format=4 uid="uid://bodsw0jyh6rn5"]
1+
[gd_resource type="Resource" script_class="ModLoaderOptionsProfile" load_steps=2 format=3 uid="uid://bodsw0jyh6rn5"]
22

33
[ext_resource type="Script" path="res://addons/mod_loader/resources/options_profile.gd" id="1"]
44

55
[resource]
66
script = ExtResource("1")
77
enable_mods = true
8-
locked_mods = Array[String]([])
8+
locked_mods = []
99
log_level = 2
10-
disabled_mods = Array[String]([])
10+
disabled_mods = []
1111
allow_modloader_autoloads_anywhere = false
1212
steam_id = 0
1313
override_path_to_mods = ""
1414
override_path_to_configs = ""
1515
override_path_to_workshop = ""
1616
ignore_deprecated_errors = false
17-
ignored_mod_names_in_log = Array[String]([])
17+
ignored_mod_names_in_log = []
1818
load_from_steam_workshop = false
1919
load_from_local = true
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
[gd_resource type="Resource" script_class="ModLoaderOptionsProfile" load_steps=2 format=4 uid="uid://cg0vv5k4o71rv"]
1+
[gd_resource type="Resource" script_class="ModLoaderOptionsProfile" load_steps=2 format=3 uid="uid://cg0vv5k4o71rv"]
22

33
[ext_resource type="Script" path="res://addons/mod_loader/resources/options_profile.gd" id="1"]
44

55
[resource]
66
script = ExtResource("1")
77
enable_mods = true
8-
locked_mods = Array[String]([])
8+
locked_mods = []
99
log_level = 2
10-
disabled_mods = Array[String]([])
10+
disabled_mods = []
1111
allow_modloader_autoloads_anywhere = false
1212
steam_id = 0
1313
override_path_to_mods = ""
1414
override_path_to_configs = ""
1515
override_path_to_workshop = ""
1616
ignore_deprecated_errors = false
17-
ignored_mod_names_in_log = Array[String]([])
17+
ignored_mod_names_in_log = []
1818
load_from_steam_workshop = true
1919
load_from_local = true

0 commit comments

Comments
 (0)