1
1
extends Resource
2
+ ## Stores and validates contents of the manifest set by the user
2
3
class_name ModDetails
3
4
5
+
6
+ ## Mod name.
7
+ ## Validated by [method is_name_or_namespace_valid]
4
8
var name := ""
9
+ ## Mod namespace, most commonly the main author.
10
+ ## Validated by [method is_name_or_namespace_valid]
5
11
var namespace := ""
6
- var version_number := "v0.0.0"
12
+ ## Semantic version. Not a number, but required to be named like this by Thunderstore
13
+ ## Validated by [method is_semver_valid]
14
+ var version_number := "0.0.0"
7
15
var description := ""
8
16
var website_url := ""
17
+ ## Used to determine mod load order
9
18
var dependencies := [] # Array[String]
10
19
11
20
var authors := [] # Array[String]
21
+ ## only used for information
12
22
var compatible_game_version := [] # Array[String]
23
+ ## only used for information
24
+ var incompatibilities := [] # Array[String]
13
25
var tags := [] # Array[String]
14
26
var description_rich := ""
15
- var incompatibilities := [] # Array[String]
16
27
var image : StreamTexture
17
28
29
+
18
30
## Required keys in a mod's manifest.json file
19
31
const REQUIRED_MANIFEST_KEYS_ROOT = [
20
32
"name" ,
@@ -36,6 +48,8 @@ const REQUIRED_MANIFEST_KEYS_EXTRA = [
36
48
]
37
49
38
50
51
+ ## Takes the manifest as [Dictionary] and validates everything.
52
+ ## Will return null if something is invalid.
39
53
func _init (manifest : Dictionary ) -> void :
40
54
if (not dict_has_fields (manifest , REQUIRED_MANIFEST_KEYS_ROOT ) or
41
55
not dict_has_fields (manifest .extra , ["godot" ]) or
@@ -50,7 +64,6 @@ func _init(manifest: Dictionary) -> void:
50
64
not is_semver_valid (version_number )):
51
65
return
52
66
53
-
54
67
description = manifest .description
55
68
website_url = manifest .website_url
56
69
dependencies = manifest .dependencies
@@ -66,14 +79,21 @@ func _init(manifest: Dictionary) -> void:
66
79
# image StreamTexture
67
80
68
81
82
+ ## Mod ID used in the mod loader
83
+ ## Format: {namespace}-{name}
69
84
func get_mod_id () -> String :
70
85
return "%s -%s " % [namespace , name ]
71
86
72
87
88
+ ## Package ID used by Thunderstore
89
+ ## Format: {namespace}-{name}-{version_number}
73
90
func get_package_id () -> String :
74
91
return "%s -%s -%s " % [namespace , name , version_number ]
75
92
76
93
94
+ ## A valid namespace may only use letters (any case), numbers and underscores
95
+ ## and has to be longer than 3 characters
96
+ ## /^[a-zA-Z0-9_]{3,}$/
77
97
static func is_name_or_namespace_valid (name : String ) -> bool :
78
98
var re := RegEx .new ()
79
99
re .compile ("^[a-zA-Z0-9_]*$" ) # alphanumeric and _
@@ -90,29 +110,37 @@ static func is_name_or_namespace_valid(name: String) -> bool:
90
110
return true
91
111
92
112
93
- func _get_string_from_dict (dict : Dictionary , key : String ) -> String :
94
- if not dict .has (key ):
95
- return ""
96
- return dict [key ]
97
-
98
-
99
- func _get_array_from_dict (dict : Dictionary , key : String ) -> Array :
100
- if not dict .has (key ):
101
- return []
102
- return dict [key ]
103
-
104
-
113
+ ## A valid semantic version should follow this format: {mayor}.{minor}.{patch}
114
+ ## reference https://semver.org/ for details
115
+ ## /^[0-9]+\\.[0-9]+\\.[0-9]+$/
105
116
static func is_semver_valid (version_number : String ) -> bool :
106
117
var re := RegEx .new ()
107
118
re .compile ("^[0-9]+\\ .[0-9]+\\ .[0-9]+$" )
108
119
109
120
if re .search (version_number ) == null :
110
- printerr ('Invalid semantic version: "%s ". You may only use numbers and periods in this format {mayor} .{minor} .{patch} ' % version_number )
121
+ printerr ('Invalid semantic version: "%s ". ' +
122
+ 'You may only use numbers and periods in this format {mayor} .{minor} .{patch} ' % version_number )
111
123
return false
112
124
113
125
return true
114
126
115
127
128
+ ## Returns an empty String if the key does not exist
129
+ static func _get_string_from_dict (dict : Dictionary , key : String ) -> String :
130
+ if not dict .has (key ):
131
+ return ""
132
+ return dict [key ]
133
+
134
+
135
+ ## Returns an empty Array if the key does not exist
136
+ static func _get_array_from_dict (dict : Dictionary , key : String ) -> Array :
137
+ if not dict .has (key ):
138
+ return []
139
+ return dict [key ]
140
+
141
+
142
+ ## Works like [method Dictionary.has_all],
143
+ ## but allows for more specific errors if a field is missing
116
144
static func dict_has_fields (dict : Dictionary , required_fields : Array ) -> bool :
117
145
var missing_fields := required_fields
118
146
0 commit comments