Last active
December 17, 2023 17:40
-
-
Save nikitalita/5c2d048e6e0b050dd7dda5b4d62f6663 to your computer and use it in GitHub Desktop.
Dumps the classdb from a running Godot 3.x game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extends Node | |
# for Godot 3.x | |
func get_type(typenum): | |
match typenum: | |
TYPE_NIL: | |
return "NIL" | |
TYPE_BOOL: | |
return "BOOL" | |
TYPE_INT: | |
return "INT" | |
TYPE_REAL: | |
return "REAL" | |
TYPE_STRING: | |
return "STRING" | |
TYPE_VECTOR2: | |
return "VECTOR2" | |
TYPE_RECT2: | |
return "RECT2" | |
TYPE_VECTOR3: | |
return "VECTOR3" | |
TYPE_TRANSFORM2D: | |
return "TRANSFORM2D" | |
TYPE_PLANE: | |
return "PLANE" | |
TYPE_QUAT: | |
return "QUAT" | |
TYPE_AABB: | |
return "AABB" | |
TYPE_BASIS: | |
return "BASIS" | |
TYPE_TRANSFORM: | |
return "TRANSFORM" | |
TYPE_COLOR: | |
return "COLOR" | |
TYPE_NODE_PATH: | |
return "NODE_PATH" | |
TYPE_RID: | |
return "RID" | |
TYPE_OBJECT: | |
return "OBJECT" | |
TYPE_DICTIONARY: | |
return "DICTIONARY" | |
TYPE_ARRAY: | |
return "ARRAY" | |
TYPE_RAW_ARRAY: | |
return "RAW_ARRAY" | |
TYPE_INT_ARRAY: | |
return "INT_ARRAY" | |
TYPE_REAL_ARRAY: | |
return "REAL_ARRAY" | |
TYPE_STRING_ARRAY: | |
return "STRING_ARRAY" | |
TYPE_VECTOR2_ARRAY: | |
return "VECTOR2_ARRAY" | |
TYPE_VECTOR3_ARRAY: | |
return "VECTOR3_ARRAY" | |
TYPE_COLOR_ARRAY: | |
return "COLOR_ARRAY" | |
TYPE_MAX: | |
return "MAX" | |
func get_hints(hint): | |
match hint: | |
PROPERTY_HINT_NONE: | |
return "" | |
PROPERTY_HINT_RANGE: | |
return "RANGE" | |
PROPERTY_HINT_EXP_RANGE: | |
return "EXP_RANGE" | |
PROPERTY_HINT_ENUM: | |
return "ENUM" | |
PROPERTY_HINT_EXP_EASING: | |
return "EXP_EASING" | |
PROPERTY_HINT_LENGTH: | |
return "LENGTH" | |
PROPERTY_HINT_KEY_ACCEL: | |
return "KEY_ACCEL" | |
PROPERTY_HINT_FLAGS: | |
return "FLAGS" | |
PROPERTY_HINT_LAYERS_2D_RENDER: | |
return "LAYERS_2D_RENDER" | |
PROPERTY_HINT_LAYERS_2D_PHYSICS: | |
return "LAYERS_2D_PHYSICS" | |
PROPERTY_HINT_LAYERS_3D_RENDER: | |
return "LAYERS_3D_RENDER" | |
PROPERTY_HINT_LAYERS_3D_PHYSICS: | |
return "LAYERS_3D_PHYSICS" | |
PROPERTY_HINT_FILE: | |
return "FILE" | |
PROPERTY_HINT_DIR: | |
return "DIR" | |
PROPERTY_HINT_GLOBAL_FILE: | |
return "GLOBAL_FILE" | |
PROPERTY_HINT_GLOBAL_DIR: | |
return "GLOBAL_DIR" | |
PROPERTY_HINT_RESOURCE_TYPE: | |
return "RESOURCE_TYPE" | |
PROPERTY_HINT_MULTILINE_TEXT: | |
return "MULTILINE_TEXT" | |
PROPERTY_HINT_PLACEHOLDER_TEXT: | |
return "PLACEHOLDER_TEXT" | |
PROPERTY_HINT_COLOR_NO_ALPHA: | |
return "COLOR_NO_ALPHA" | |
PROPERTY_HINT_IMAGE_COMPRESS_LOSSY: | |
return "IMAGE_COMPRESS_LOSSY" | |
PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS: | |
return "IMAGE_COMPRESS_LOSSLESS" | |
return "<ERROR>" | |
func get_usage(usage): | |
var arr = [] | |
if usage & PROPERTY_USAGE_STORAGE: | |
arr.push_back("STORAGE") | |
if usage & PROPERTY_USAGE_EDITOR: | |
arr.push_back("EDITOR") | |
if usage & PROPERTY_USAGE_NETWORK: | |
arr.push_back("NETWORK") | |
if usage & PROPERTY_USAGE_EDITOR_HELPER: | |
arr.push_back("EDITOR_HELPER") | |
if usage & PROPERTY_USAGE_CHECKABLE: | |
arr.push_back("CHECKABLE") | |
if usage & PROPERTY_USAGE_CHECKED: | |
arr.push_back("CHECKED") | |
if usage & PROPERTY_USAGE_INTERNATIONALIZED: | |
arr.push_back("INTERNATIONALIZED") | |
if usage & PROPERTY_USAGE_GROUP: | |
arr.push_back("GROUP") | |
if usage & PROPERTY_USAGE_CATEGORY: | |
arr.push_back("CATEGORY") | |
if usage & PROPERTY_USAGE_NO_INSTANCE_STATE: | |
arr.push_back("NO_INSTANCE_STATE") | |
if usage & PROPERTY_USAGE_RESTART_IF_CHANGED: | |
arr.push_back("RESTART_IF_CHANGED") | |
if usage & PROPERTY_USAGE_SCRIPT_VARIABLE: | |
arr.push_back("SCRIPT_VARIABLE") | |
if usage & PROPERTY_USAGE_DEFAULT: | |
arr.push_back("DEFAULT") | |
if usage & PROPERTY_USAGE_DEFAULT_INTL: | |
arr.push_back("DEFAULT_INTL") | |
if usage & PROPERTY_USAGE_NOEDITOR: | |
arr.push_back("NOEDITOR") | |
arr.sort() | |
return arr | |
class DictSorter: | |
static func sort(a,b): | |
if a["name"] < b["name"]: | |
return true | |
return false | |
func parse_prop(prop): | |
prop["hint"] = get_hints(prop["hint"]) | |
prop["type"] = get_type(prop["type"]) | |
prop.erase("hint_string") # never of any value, just dupes "class_name" field | |
return prop | |
func parse_props(props): | |
var arr = [] | |
for prop in props: | |
arr.push_back(parse_prop(prop)) | |
arr.sort_custom(DictSorter, "sort") | |
return arr | |
func parse_methods(methods): | |
var arr = [] | |
for method in methods: | |
method["args"] = parse_props(method["args"]) | |
method["return"] = parse_prop(method["return"]) | |
method.erase("id") # useless for diffing | |
arr.push_back(method) | |
arr.sort_custom(DictSorter, "sort") | |
return arr | |
func get_pretty_json_string(obj, indent_increment : int = 0): | |
var pretty : String = "" | |
var indent : String = " " | |
var quote : String = "\"" | |
var newline : String = "\n" | |
var colon : String = ":" | |
var openbracket : String = "{" | |
var closebracket : String = "}" | |
var space : String = " " | |
var comma : String = "," | |
var arr_open_bracket = "[ " | |
var arr_close_bracket = " ]" | |
var white_space = "" | |
for i in range (indent_increment): | |
white_space += indent | |
var is_not_last : bool = true | |
var element_counter : int = 0 | |
match typeof(obj): | |
TYPE_ARRAY, TYPE_RAW_ARRAY, TYPE_INT_ARRAY, TYPE_REAL_ARRAY, TYPE_STRING_ARRAY, TYPE_VECTOR2_ARRAY, TYPE_VECTOR3_ARRAY, TYPE_COLOR_ARRAY: | |
if len(obj) == 0: | |
return "[]" | |
comma = ", " | |
var sub_pretty = "" | |
var has_dict = false | |
var total_str_len = 0 | |
var stringified_arr: PoolStringArray = [] | |
for element in obj: | |
if typeof(element) == TYPE_DICTIONARY: | |
has_dict = true | |
var thing = get_pretty_json_string(element, indent_increment + 1) | |
stringified_arr.push_back(thing) | |
total_str_len += len(thing) + (len(stringified_arr) * 2) | |
var arr_join_string = ", " | |
if total_str_len > (40 - (indent_increment * len(indent))) or has_dict: | |
arr_join_string = ",\n" + white_space + indent | |
arr_open_bracket = "[\n" + white_space + indent | |
arr_close_bracket = "\n" + white_space + "]" | |
pretty += arr_open_bracket + stringified_arr.join(arr_join_string) + arr_close_bracket | |
TYPE_BOOL, TYPE_NIL: | |
pretty += str(obj).to_lower() | |
TYPE_INT, TYPE_REAL: | |
pretty += str(obj) | |
TYPE_DICTIONARY: | |
pretty += openbracket | |
for element in obj.keys(): | |
element_counter += 1 | |
if element == "default_args": | |
pass | |
pretty += newline | |
for i in range (indent_increment + 1): | |
pretty += indent | |
pretty += quote + str(element).json_escape() + quote + space + colon + space | |
pretty += self.get_pretty_json_string(obj.get(element), indent_increment + 1) | |
if (not len(obj.keys()) <= 1) and element_counter < len(obj.keys()): | |
pretty += comma | |
pretty += newline | |
for i in range (indent_increment): | |
pretty += indent | |
pretty += closebracket | |
_: | |
pretty = quote + str(obj).json_escape() + quote | |
return pretty | |
func dump_classdb(): | |
var _list = Array(ClassDB.get_class_list()) | |
_list.sort() | |
var jsonobj: Array = [] | |
for cls in _list: | |
var dict = Dictionary() | |
#dict["category"] = ClassDB.class_get_category(cls) # not present in non-debug builds | |
dict["class_name"] = cls | |
dict["parent"] = ClassDB.get_parent_class(cls) | |
dict["methods"] = parse_methods(ClassDB.class_get_method_list(cls, true)) | |
dict["signals"] = parse_methods(ClassDB.class_get_signal_list(cls, true)) | |
dict["props"] = parse_props(ClassDB.class_get_property_list(cls, true)) | |
var enums = Array(ClassDB.class_get_integer_constant_list(cls, true)) | |
enums.sort() | |
dict["enums"] = enums | |
jsonobj.push_back(dict) | |
var version = Engine.get_version_info()["string"].replace(" ","_").replace("(","").replace(")","") | |
var json_texts | |
#var text = JSON.print(jsonobj, " ") | |
var text = get_pretty_json_string(jsonobj, 1) | |
# Note: If writing to the filesystem is disabled in the Godot binary this is being tested against, | |
# try using `set_clipboard()` instead | |
var f = File.new() | |
f.open("classdb_dump_" + version + ".json", File.WRITE) | |
f.store_string(text) | |
f.close() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment