Skip to content

Instantly share code, notes, and snippets.

@nikitalita
Last active December 17, 2023 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikitalita/5c2d048e6e0b050dd7dda5b4d62f6663 to your computer and use it in GitHub Desktop.
Save nikitalita/5c2d048e6e0b050dd7dda5b4d62f6663 to your computer and use it in GitHub Desktop.
Dumps the classdb from a running Godot 3.x game
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