From 9843807154aa70324c84692ce9d3b54414e2b5e0 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Thu, 25 May 2023 22:35:16 +0100 Subject: Added compatibility-mode command line argument --- extension/src/LoadGameOpenVic.cpp | 9 +- game/project.godot | 1 + game/src/ArgumentOption.gd | 60 ------ game/src/ArgumentParser.gd | 259 ----------------------- game/src/ArgumentParser.tscn | 24 --- game/src/Autoload/Arguments/ArgumentOption.gd | 60 ++++++ game/src/Autoload/Arguments/ArgumentParser.gd | 267 ++++++++++++++++++++++++ game/src/Autoload/Arguments/ArgumentParser.tscn | 32 +++ game/src/Autoload/Events.gd | 19 +- game/src/GameStart.tscn | 5 +- game/src/MusicConductor/SongInfo.gd | 2 +- 11 files changed, 379 insertions(+), 359 deletions(-) delete mode 100644 game/src/ArgumentOption.gd delete mode 100644 game/src/ArgumentParser.gd delete mode 100644 game/src/ArgumentParser.tscn create mode 100644 game/src/Autoload/Arguments/ArgumentOption.gd create mode 100644 game/src/Autoload/Arguments/ArgumentParser.gd create mode 100644 game/src/Autoload/Arguments/ArgumentParser.tscn diff --git a/extension/src/LoadGameOpenVic.cpp b/extension/src/LoadGameOpenVic.cpp index ce1bf39..27fb265 100644 --- a/extension/src/LoadGameOpenVic.cpp +++ b/extension/src/LoadGameOpenVic.cpp @@ -19,14 +19,15 @@ static Error _load_json_file(String const& file_description, String const& file_ return err == OK ? FAILED : err; } const String json_string = file->get_as_text(); - JSON json; - err = json.parse(json_string); + Ref json; + json.instantiate(); + err = json->parse(json_string); if (err != OK) { UtilityFunctions::push_error("Failed to parse ", file_description, " file as JSON: ", file_path, - "\nError at line ", json.get_error_line(), ": ", json.get_error_message()); + "\nError at line ", json->get_error_line(), ": ", json->get_error_message()); return err; } - result = json.get_data(); + result = json->get_data(); return err; } diff --git a/game/project.godot b/game/project.godot index 441001d..3bb2438 100644 --- a/game/project.godot +++ b/game/project.godot @@ -21,6 +21,7 @@ config/project_settings_override.template="user://settings.cfg" [autoload] +ArgumentParser="*res://src/Autoload/Arguments/ArgumentParser.tscn" Events="*res://src/Autoload/Events.gd" Resolution="*res://src/Autoload/Resolution.gd" SoundManager="*res://src/Autoload/SoundManager.gd" diff --git a/game/src/ArgumentOption.gd b/game/src/ArgumentOption.gd deleted file mode 100644 index f14cef0..0000000 --- a/game/src/ArgumentOption.gd +++ /dev/null @@ -1,60 +0,0 @@ -@tool -class_name ArgumentOption -extends Resource - -@export var name : StringName -@export var aliases : Array[StringName] = [] -@export var type : Variant.Type : - get: return type - set(v): - type = v - match v: - TYPE_BOOL: default_value = false - TYPE_INT: default_value = 0 - TYPE_FLOAT: default_value = 0.0 - TYPE_STRING: default_value = "" - TYPE_STRING_NAME: default_value = &"" - TYPE_COLOR: default_value = Color() - _: default_value = null - notify_property_list_changed() -var default_value -@export var description : String - -func _init(_name = "", _type = TYPE_NIL, _description = "", default = null): - name = _name - type = _type - if default != null and typeof(default) == type: - default_value = default - description = _description - -func add_alias(alias : StringName) -> ArgumentOption: - aliases.append(alias) - return self - -func get_type_string() -> StringName: - match type: - TYPE_NIL: return "null" - TYPE_BOOL: return "boolean" - TYPE_INT: return "integer" - TYPE_FLOAT: return "float" - TYPE_STRING, TYPE_STRING_NAME: return "string" - TYPE_COLOR: return "color" - return "" - -func _get(property): - if property == "default_value": return default_value - -func _set(property, value): - if property == "default_value": - default_value = value - return true - -func _get_property_list(): - var properties := [] - - properties.append({ - "name": "default_value", - "type": type - }) - - return properties diff --git a/game/src/ArgumentParser.gd b/game/src/ArgumentParser.gd deleted file mode 100644 index f1ee371..0000000 --- a/game/src/ArgumentParser.gd +++ /dev/null @@ -1,259 +0,0 @@ -@tool -extends Node - -const argument_setting_path := &"openvic/data/arguments" - -@export var option_array : Array[ArgumentOption] = [ - ArgumentOption.new( - "help", - TYPE_BOOL, - "Displays help and quits.", - false - ).add_alias(&"h") -] - -const color_name_array : PackedStringArray =[ - "aliceblue", "antiquewhite", "aqua", "aquamarine", - "azure", "beige", "bisque", "black", "blanchedalmond", - "blue", "blueviolet", "brown", "burlywood", "cadetblue", - "chartreuse", "chocolate", "coral", "cornflower", "cornsilk", - "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", - "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", - "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", - "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", - "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", - "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", - "gold", "goldenrod", "gray", "green", "greenyellow", "honeydew", - "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", - "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", - "lightcyan", "lightgoldenrod", "lightgray", "lightgreen", "lightpink", - "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", - "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", - "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", - "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", - "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", - "mistyrose", "moccasin", "navajowhite", "navyblue", "oldlace", "olive", - "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", - "palegreen", "paleturquoise", "palevioletred", "papayawhip", - "peachpuff", "peru", "pink", "plum", "powderblue", "purple", - "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", - "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", - "skyblue", "slateblue", "slategray", "snow", "springgreen", "steelblue", - "tan", "teal", "thistle", "tomato", "transparent", "turquoise", "violet", - "webgray", "webgreen", "webmaroon", "webpurple", "wheat", "white", - "whitesmoke", "yellow", "yellowgreen" -] - -func _parse_value(arg_name : StringName, value_string : String, type : Variant.Type) -> Variant: - match type: - TYPE_NIL: return null - TYPE_BOOL: - value_string = value_string.to_lower() - if value_string == "true" or value_string == "t" or value_string == "yes" or value_string == "y": - return true - if value_string == "false" or value_string == "f" or value_string == "no" or value_string == "n": - return false - return true - TYPE_INT: - return value_string.to_int() - TYPE_FLOAT: - return value_string.to_float() - TYPE_STRING, TYPE_STRING_NAME: - return value_string - TYPE_COLOR: - if Color.html_is_valid(value_string) or value_string.to_lower() in color_name_array: - return Color.from_string(value_string, Color()) - push_error("'%s' must be an html Color or Color name, '%s' is an invalid value." % [arg_name, value_string]) - return null - # Unsupported types - TYPE_VECTOR2, \ - TYPE_VECTOR2I, \ - TYPE_VECTOR3, \ - TYPE_VECTOR3I, \ - TYPE_VECTOR4, \ - TYPE_VECTOR4I, \ - TYPE_RECT2, \ - TYPE_RECT2I: - push_warning("Value type '%s' may not be supported." % type) - var data_array = value_string.lstrip("(").rstrip(")").split(",", false) - for index in range(data_array.size()): - data_array[index] = " " + data_array[index].strip_edges() - match type: - TYPE_VECTOR2: - if data_array.size() != 2: - push_error("'%s' value must be a Vector2, '%s' is an invalid value." % [arg_name, value_string]) - return null - return str_to_var("Vector2(%s )" % ",".join(data_array)) - TYPE_VECTOR2I: - if data_array.size() != 2: - push_error("'%s' value must be a Vector2i, '%s' is an invalid value." % [arg_name, value_string]) - return null - return str_to_var("Vector2i(%s )" % ",".join(data_array)) - TYPE_VECTOR3: - if data_array.size() != 2: - push_error("'%s' value must be a Vector3, '%s' is an invalid value." % [arg_name, value_string]) - return null - return str_to_var("Vector3(%s )" % ",".join(data_array)) - TYPE_VECTOR3I: - if data_array.size() != 2: - push_error("'%s' value must be a Vector3i, '%s' is an invalid value." % [arg_name, value_string]) - return null - return str_to_var("Vector3i(%s )" % ",".join(data_array)) - TYPE_VECTOR4: - if data_array.size() != 2: - push_error("'%s' value must be a Vector4, '%s' is an invalid value." % [arg_name, value_string]) - return null - return str_to_var("Vector4(%s )" % ",".join(data_array)) - TYPE_VECTOR4I: - if data_array.size() != 2: - push_error("'%s' value must be a Vector4i, '%s' is an invalid value." % [arg_name, value_string]) - return null - return str_to_var("Vector4i(%s )" % ",".join(data_array)) - TYPE_RECT2: - if data_array.size() != 2: - push_error("'%s' value must be a Rect2, '%s' is an invalid value." % [arg_name, value_string]) - return null - return str_to_var("Rect2(%s )" % ",".join(data_array)) - TYPE_RECT2I: - if data_array.size() != 2: - push_error("'%s' value must be a Rect2i, '%s' is an invalid value." % [arg_name, value_string]) - return null - return str_to_var("Rect2i(%s )" % ",".join(data_array)) - _: - push_error("'%s' value of type '%s' requested but could not be parsed." % [arg_name, type]) - return null - - return null - -# Missing types -# TYPE_TRANSFORM2D = 11 -# TYPE_VECTOR4 = 12 -# TYPE_VECTOR4I = 13 -# TYPE_PLANE = 14 -# TYPE_QUATERNION = 15 -# TYPE_AABB = 16 -# TYPE_BASIS = 17 -# TYPE_TRANSFORM3D = 18 -# TYPE_PROJECTION = 19 -# TYPE_NODE_PATH = 22 -# TYPE_RID = 23 -# TYPE_OBJECT = 24 -# TYPE_CALLABLE = 25 -# TYPE_SIGNAL = 26 -# TYPE_DICTIONARY = 27 -# TYPE_ARRAY = 28 -# TYPE_PACKED_BYTE_ARRAY = 29 -# TYPE_PACKED_INT32_ARRAY = 30 -# TYPE_PACKED_INT64_ARRAY = 31 -# TYPE_PACKED_FLOAT32_ARRAY = 32 -# TYPE_PACKED_FLOAT64_ARRAY = 33 -# TYPE_PACKED_STRING_ARRAY = 34 -# TYPE_PACKED_VECTOR2_ARRAY = 35 -# TYPE_PACKED_VECTOR3_ARRAY = 36 -# TYPE_PACKED_COLOR_ARRAY = 37 - -func _parse_argument_list(dictionary : Dictionary, arg_list : PackedStringArray) -> Dictionary: - var current_key : String = "" - var current_option : ArgumentOption = null - for arg in arg_list: - if current_option != null and not arg.begins_with("-"): - var result = _parse_value(current_key, arg, current_option.type) - if result != null: - dictionary[current_option.name] = result - current_option = null - continue - - if current_option != null: - push_warning("Valid argument '%s' was not set as a value, skipping." % current_key) - - if arg.begins_with("-"): - current_option = null - arg = arg.substr(1) - var key := &"" - var value := &"" - - # Support for Unix shorthand of multiple boolean arguments - # eg: "-abc" means a == true, b == true, c == true - if arg.length() > 1 and arg[0] != "-" and arg[1] != "=": - for c in arg: - for o in option_array: - if o.aliases.any(func(v): return c == v): - dictionary[o.name] = true - continue - - # Support for = key/value split - # eg: "-v=5" and "--value=5" means v == 5 and value == 5 - var first_equal := arg.find("=") - if first_equal > -1: - key = arg.substr(0, first_equal - 1) - value = arg.substr(first_equal + 1) - else: - key = arg - - # Removes - for full name arguments - if key.begins_with("-"): - key = key.substr(1) - - for o in option_array: - if key == o.name or o.aliases.any(func(v): return key == v): - current_option = o - break - - if current_option == null: - push_warning("Invalid argument '%s' found, skipping." % key) - continue - - current_key = key - var arg_result = _parse_value(key, value, current_option.type) - if arg_result != null: - dictionary[current_option.name] = arg_result - current_option = null - - return dictionary - -func _print_help(): - var project_name : StringName = ProjectSettings.get_setting_with_override(&"application/config/name") - var project_version : String = _GIT_INFO_.tag - var project_hash : String = _GIT_INFO_.short_hash - var project_website : String = "https://openvic.com" - var project_description : String = ProjectSettings.get_setting_with_override(&"application/config/description") - print_rich( -""" -%s - %s - %s - %s -%s - -%s - -Options: -""" - % [ - project_name, - project_version, - project_hash, - project_website, - project_description, - "usage: %s [options]" % OS.get_executable_path().get_file() - ] - ) - for option in option_array: - print_rich(" --%s%s%s" % [ - (option.name + (",-%s" % (",-".join(option.aliases)) if option.aliases.size() > 0 else "")).rpad(45), - ("Type: %s - Default Value: %s" % [option.get_type_string(), option.default_value]).rpad(45), - option.description - ]) -func _ready(): - if Engine.is_editor_hint(): return - - var argument_dictionary : Dictionary = {} - if ProjectSettings.has_setting(argument_setting_path): - argument_dictionary = ProjectSettings.get_setting_with_override(argument_setting_path) - for option in option_array: - argument_dictionary[option.name] = option.default_value - - _parse_argument_list(argument_dictionary, OS.get_cmdline_args()) - _parse_argument_list(argument_dictionary, OS.get_cmdline_user_args()) - - ProjectSettings.set_setting(argument_setting_path, argument_dictionary) - if argument_dictionary[&"help"]: - _print_help() - get_tree().quit() diff --git a/game/src/ArgumentParser.tscn b/game/src/ArgumentParser.tscn deleted file mode 100644 index 964c19e..0000000 --- a/game/src/ArgumentParser.tscn +++ /dev/null @@ -1,24 +0,0 @@ -[gd_scene load_steps=5 format=3 uid="uid://dayjmgc34tqo6"] - -[ext_resource type="Script" path="res://src/ArgumentParser.gd" id="1_8e7gi"] -[ext_resource type="Script" path="res://src/ArgumentOption.gd" id="2_f3c26"] - -[sub_resource type="Resource" id="Resource_tq3y4"] -script = ExtResource("2_f3c26") -name = &"help" -aliases = Array[StringName]([&"h"]) -type = 1 -description = "Displays help and quits." -default_value = false - -[sub_resource type="Resource" id="Resource_j1to4"] -script = ExtResource("2_f3c26") -name = &"game-debug" -aliases = Array[StringName]([&"d", &"-debug", &"-debug-mode"]) -type = 1 -description = "Start in debug mode." -default_value = false - -[node name="ArgumentParser" type="Node"] -script = ExtResource("1_8e7gi") -option_array = Array[ExtResource("2_f3c26")]([SubResource("Resource_tq3y4"), SubResource("Resource_j1to4")]) diff --git a/game/src/Autoload/Arguments/ArgumentOption.gd b/game/src/Autoload/Arguments/ArgumentOption.gd new file mode 100644 index 0000000..f14cef0 --- /dev/null +++ b/game/src/Autoload/Arguments/ArgumentOption.gd @@ -0,0 +1,60 @@ +@tool +class_name ArgumentOption +extends Resource + +@export var name : StringName +@export var aliases : Array[StringName] = [] +@export var type : Variant.Type : + get: return type + set(v): + type = v + match v: + TYPE_BOOL: default_value = false + TYPE_INT: default_value = 0 + TYPE_FLOAT: default_value = 0.0 + TYPE_STRING: default_value = "" + TYPE_STRING_NAME: default_value = &"" + TYPE_COLOR: default_value = Color() + _: default_value = null + notify_property_list_changed() +var default_value +@export var description : String + +func _init(_name = "", _type = TYPE_NIL, _description = "", default = null): + name = _name + type = _type + if default != null and typeof(default) == type: + default_value = default + description = _description + +func add_alias(alias : StringName) -> ArgumentOption: + aliases.append(alias) + return self + +func get_type_string() -> StringName: + match type: + TYPE_NIL: return "null" + TYPE_BOOL: return "boolean" + TYPE_INT: return "integer" + TYPE_FLOAT: return "float" + TYPE_STRING, TYPE_STRING_NAME: return "string" + TYPE_COLOR: return "color" + return "" + +func _get(property): + if property == "default_value": return default_value + +func _set(property, value): + if property == "default_value": + default_value = value + return true + +func _get_property_list(): + var properties := [] + + properties.append({ + "name": "default_value", + "type": type + }) + + return properties diff --git a/game/src/Autoload/Arguments/ArgumentParser.gd b/game/src/Autoload/Arguments/ArgumentParser.gd new file mode 100644 index 0000000..ce89dd8 --- /dev/null +++ b/game/src/Autoload/Arguments/ArgumentParser.gd @@ -0,0 +1,267 @@ +@tool +extends Node + +const argument_setting_path := &"openvic/data/arguments" + +@export var option_array : Array[ArgumentOption] = [ + ArgumentOption.new( + "help", + TYPE_BOOL, + "Displays help and quits.", + false + ).add_alias(&"h") +] + +const color_name_array : PackedStringArray =[ + "aliceblue", "antiquewhite", "aqua", "aquamarine", + "azure", "beige", "bisque", "black", "blanchedalmond", + "blue", "blueviolet", "brown", "burlywood", "cadetblue", + "chartreuse", "chocolate", "coral", "cornflower", "cornsilk", + "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", + "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", + "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", + "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", + "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", + "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", + "gold", "goldenrod", "gray", "green", "greenyellow", "honeydew", + "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", + "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", + "lightcyan", "lightgoldenrod", "lightgray", "lightgreen", "lightpink", + "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", + "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", + "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", + "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", + "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", + "mistyrose", "moccasin", "navajowhite", "navyblue", "oldlace", "olive", + "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", + "palegreen", "paleturquoise", "palevioletred", "papayawhip", + "peachpuff", "peru", "pink", "plum", "powderblue", "purple", + "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", + "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", + "skyblue", "slateblue", "slategray", "snow", "springgreen", "steelblue", + "tan", "teal", "thistle", "tomato", "transparent", "turquoise", "violet", + "webgray", "webgreen", "webmaroon", "webpurple", "wheat", "white", + "whitesmoke", "yellow", "yellowgreen" +] + +func _parse_value(arg_name : StringName, value_string : String, type : Variant.Type) -> Variant: + match type: + TYPE_NIL: return null + TYPE_BOOL: + value_string = value_string.to_lower() + if value_string == "true" or value_string == "t" or value_string == "yes" or value_string == "y": + return true + if value_string == "false" or value_string == "f" or value_string == "no" or value_string == "n": + return false + push_error("'%s' must be a valid boolean, '%s' is an invalid value." % [arg_name, value_string]) + return null + TYPE_INT: + if value_string.is_valid_int(): + return value_string.to_int() + push_error("'%s' must be a valid integer, '%s' is an invalid value." % [arg_name, value_string]) + return null + TYPE_FLOAT: + if value_string.is_valid_float(): + return value_string.to_float() + push_error("'%s' must be a valid float, '%s' is an invalid value." % [arg_name, value_string]) + return null + TYPE_STRING, TYPE_STRING_NAME: + return value_string + TYPE_COLOR: + if Color.html_is_valid(value_string) or value_string.to_lower() in color_name_array: + return Color.from_string(value_string, Color()) + push_error("'%s' must be an html Color or Color name, '%s' is an invalid value." % [arg_name, value_string]) + return null + # Unsupported types + TYPE_VECTOR2, \ + TYPE_VECTOR2I, \ + TYPE_VECTOR3, \ + TYPE_VECTOR3I, \ + TYPE_VECTOR4, \ + TYPE_VECTOR4I, \ + TYPE_RECT2, \ + TYPE_RECT2I: + push_warning("Value type '%s' may not be supported." % type) + var data_array = value_string.lstrip("(").rstrip(")").split(",", false) + for index in range(data_array.size()): + data_array[index] = " " + data_array[index].strip_edges() + match type: + TYPE_VECTOR2: + if data_array.size() != 2: + push_error("'%s' value must be a Vector2, '%s' is an invalid value." % [arg_name, value_string]) + return null + return str_to_var("Vector2(%s )" % ",".join(data_array)) + TYPE_VECTOR2I: + if data_array.size() != 2: + push_error("'%s' value must be a Vector2i, '%s' is an invalid value." % [arg_name, value_string]) + return null + return str_to_var("Vector2i(%s )" % ",".join(data_array)) + TYPE_VECTOR3: + if data_array.size() != 2: + push_error("'%s' value must be a Vector3, '%s' is an invalid value." % [arg_name, value_string]) + return null + return str_to_var("Vector3(%s )" % ",".join(data_array)) + TYPE_VECTOR3I: + if data_array.size() != 2: + push_error("'%s' value must be a Vector3i, '%s' is an invalid value." % [arg_name, value_string]) + return null + return str_to_var("Vector3i(%s )" % ",".join(data_array)) + TYPE_VECTOR4: + if data_array.size() != 2: + push_error("'%s' value must be a Vector4, '%s' is an invalid value." % [arg_name, value_string]) + return null + return str_to_var("Vector4(%s )" % ",".join(data_array)) + TYPE_VECTOR4I: + if data_array.size() != 2: + push_error("'%s' value must be a Vector4i, '%s' is an invalid value." % [arg_name, value_string]) + return null + return str_to_var("Vector4i(%s )" % ",".join(data_array)) + TYPE_RECT2: + if data_array.size() != 2: + push_error("'%s' value must be a Rect2, '%s' is an invalid value." % [arg_name, value_string]) + return null + return str_to_var("Rect2(%s )" % ",".join(data_array)) + TYPE_RECT2I: + if data_array.size() != 2: + push_error("'%s' value must be a Rect2i, '%s' is an invalid value." % [arg_name, value_string]) + return null + return str_to_var("Rect2i(%s )" % ",".join(data_array)) + _: + push_error("'%s' value of type '%s' requested but could not be parsed." % [arg_name, type]) + return null + + return null + +# Missing types +# TYPE_TRANSFORM2D = 11 +# TYPE_VECTOR4 = 12 +# TYPE_VECTOR4I = 13 +# TYPE_PLANE = 14 +# TYPE_QUATERNION = 15 +# TYPE_AABB = 16 +# TYPE_BASIS = 17 +# TYPE_TRANSFORM3D = 18 +# TYPE_PROJECTION = 19 +# TYPE_NODE_PATH = 22 +# TYPE_RID = 23 +# TYPE_OBJECT = 24 +# TYPE_CALLABLE = 25 +# TYPE_SIGNAL = 26 +# TYPE_DICTIONARY = 27 +# TYPE_ARRAY = 28 +# TYPE_PACKED_BYTE_ARRAY = 29 +# TYPE_PACKED_INT32_ARRAY = 30 +# TYPE_PACKED_INT64_ARRAY = 31 +# TYPE_PACKED_FLOAT32_ARRAY = 32 +# TYPE_PACKED_FLOAT64_ARRAY = 33 +# TYPE_PACKED_STRING_ARRAY = 34 +# TYPE_PACKED_VECTOR2_ARRAY = 35 +# TYPE_PACKED_VECTOR3_ARRAY = 36 +# TYPE_PACKED_COLOR_ARRAY = 37 + +func _parse_argument_list(dictionary : Dictionary, arg_list : PackedStringArray) -> Dictionary: + var current_key : String = "" + var current_option : ArgumentOption = null + for arg in arg_list: + if current_option != null and not arg.begins_with("-"): + var result = _parse_value(current_key, arg, current_option.type) + if result != null: + dictionary[current_option.name] = result + current_option = null + continue + + if current_option != null: + push_warning("Valid argument '%s' was not set as a value, skipping." % current_key) + + if arg.begins_with("-"): + current_option = null + arg = arg.substr(1) + var key := &"" + var value := &"" + + # Support for Unix shorthand of multiple boolean arguments + # eg: "-abc" means a == true, b == true, c == true + if arg.length() > 1 and arg[0] != "-" and arg[1] != "=": + for c in arg: + for o in option_array: + if o.aliases.any(func(v): return c == v): + dictionary[o.name] = true + continue + + # Support for = key/value split + # eg: "-v=5" and "--value=5" means v == 5 and value == 5 + var first_equal := arg.find("=") + if first_equal > -1: + key = arg.substr(0, first_equal - 1) + value = arg.substr(first_equal + 1) + else: + key = arg + + # Removes - for full name arguments + if key.begins_with("-"): + key = key.substr(1) + + for o in option_array: + if key == o.name or o.aliases.any(func(v): return key == v): + current_option = o + break + + if current_option == null: + push_warning("Invalid argument '%s' found, skipping." % key) + continue + + current_key = key + if first_equal > -1: + var arg_result = _parse_value(key, value, current_option.type) + if arg_result != null: + dictionary[current_option.name] = arg_result + current_option = null + + return dictionary + +func _print_help(): + var project_name : StringName = ProjectSettings.get_setting_with_override(&"application/config/name") + var project_version : String = _GIT_INFO_.tag + var project_hash : String = _GIT_INFO_.short_hash + var project_website : String = "https://openvic.com" + var project_description : String = ProjectSettings.get_setting_with_override(&"application/config/description") + print_rich( +""" +%s - %s - %s - %s +%s + +%s + +Options: +""" + % [ + project_name, + project_version, + project_hash, + project_website, + project_description, + "usage: %s [options]" % OS.get_executable_path().get_file() + ] + ) + for option in option_array: + print_rich(" --%s%s%s" % [ + (option.name + (",-%s" % (",-".join(option.aliases)) if option.aliases.size() > 0 else "")).rpad(45), + ("Type: %s - Default Value: %s" % [option.get_type_string(), option.default_value]).rpad(45), + option.description + ]) +func _ready(): + if Engine.is_editor_hint(): return + + var argument_dictionary : Dictionary = {} + if ProjectSettings.has_setting(argument_setting_path): + argument_dictionary = ProjectSettings.get_setting_with_override(argument_setting_path) + for option in option_array: + argument_dictionary[option.name] = option.default_value + + _parse_argument_list(argument_dictionary, OS.get_cmdline_args()) + _parse_argument_list(argument_dictionary, OS.get_cmdline_user_args()) + + ProjectSettings.set_setting(argument_setting_path, argument_dictionary) + if argument_dictionary[&"help"]: + _print_help() + get_tree().quit() diff --git a/game/src/Autoload/Arguments/ArgumentParser.tscn b/game/src/Autoload/Arguments/ArgumentParser.tscn new file mode 100644 index 0000000..8fda8f1 --- /dev/null +++ b/game/src/Autoload/Arguments/ArgumentParser.tscn @@ -0,0 +1,32 @@ +[gd_scene load_steps=6 format=3 uid="uid://dayjmgc34tqo6"] + +[ext_resource type="Script" path="res://src/Autoload/Arguments/ArgumentParser.gd" id="1_pc7xr"] +[ext_resource type="Script" path="res://src/Autoload/Arguments/ArgumentOption.gd" id="2_4hguj"] + +[sub_resource type="Resource" id="Resource_tq3y4"] +script = ExtResource("2_4hguj") +name = &"help" +aliases = Array[StringName]([&"h"]) +type = 1 +description = "Displays help and quits." +default_value = false + +[sub_resource type="Resource" id="Resource_j1to4"] +script = ExtResource("2_4hguj") +name = &"game-debug" +aliases = Array[StringName]([&"d", &"-debug", &"-debug-mode"]) +type = 1 +description = "Start in debug mode." +default_value = false + +[sub_resource type="Resource" id="Resource_tiax1"] +script = ExtResource("2_4hguj") +name = &"compatibility-mode" +aliases = Array[StringName]([&"-compat"]) +type = 4 +description = "Load Victoria 2 assets from this path." +default_value = "" + +[node name="ArgumentParser" type="Node"] +script = ExtResource("1_pc7xr") +option_array = Array[ExtResource("2_4hguj")]([SubResource("Resource_tq3y4"), SubResource("Resource_j1to4"), SubResource("Resource_tiax1")]) diff --git a/game/src/Autoload/Events.gd b/game/src/Autoload/Events.gd index 8800041..4387cc7 100644 --- a/game/src/Autoload/Events.gd +++ b/game/src/Autoload/Events.gd @@ -17,20 +17,25 @@ var _define_filepaths_dict : Dictionary = { GameSingleton.get_good_icons_dir_key(): "res://art/economy/goods" } -# Set this to your Vic2 install dir or a mod's dir to enable compatibility mode -# (this won't work for mods which rely on vanilla map assets, copy missing assets -# into the mod's dir for a temporary fix) -const _compatibility_mode_path : String = "" - # REQUIREMENTS # * FS-333, FS-334, FS-335, FS-341 func _ready(): GameSingleton.setup_logger() + # Set this to your Vic2 install dir or a mod's dir to enable compatibility mode + # (this won't work for mods which rely on vanilla map assets, copy missing assets + # into the mod's dir for a temporary fix) + # Usage: OpenVic --compatibility-mode + + var compatibility_mode_path : String + if ProjectSettings.has_setting(ArgumentParser.argument_setting_path): + var arg_dictionary : Dictionary = ProjectSettings.get_setting(ArgumentParser.argument_setting_path) + compatibility_mode_path = arg_dictionary.get(&"compatibility-mode", compatibility_mode_path) + var start := Time.get_ticks_usec() - if _compatibility_mode_path: - if GameSingleton.load_defines_compatibility_mode(_compatibility_mode_path) != OK: + if compatibility_mode_path: + if GameSingleton.load_defines_compatibility_mode(compatibility_mode_path) != OK: push_error("Errors loading game defines!") else: if GameSingleton.load_defines(_define_filepaths_dict) != OK: diff --git a/game/src/GameStart.tscn b/game/src/GameStart.tscn index d5f9d45..2046bb5 100644 --- a/game/src/GameStart.tscn +++ b/game/src/GameStart.tscn @@ -1,6 +1,5 @@ -[gd_scene load_steps=7 format=3 uid="uid://1udsn4mggep2"] +[gd_scene load_steps=6 format=3 uid="uid://1udsn4mggep2"] -[ext_resource type="PackedScene" uid="uid://dayjmgc34tqo6" path="res://src/ArgumentParser.tscn" id="1_oe61r"] [ext_resource type="PackedScene" uid="uid://o4u142w4qkln" path="res://src/GameMenu.tscn" id="1_wlojq"] [ext_resource type="Script" path="res://src/SplashContainer.gd" id="2_xmcgv"] [ext_resource type="Texture2D" uid="uid://deef5hufq0j61" path="res://splash_assets/splash_end.png" id="3_qfv12"] @@ -15,8 +14,6 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -[node name="ArgumentParser" parent="." instance=ExtResource("1_oe61r")] - [node name="GameMenu" parent="." instance=ExtResource("1_wlojq")] visible = false layout_mode = 1 diff --git a/game/src/MusicConductor/SongInfo.gd b/game/src/MusicConductor/SongInfo.gd index f7343c0..1ee9adc 100644 --- a/game/src/MusicConductor/SongInfo.gd +++ b/game/src/MusicConductor/SongInfo.gd @@ -1,4 +1,4 @@ -extends Node +extends Resource class_name SongInfo var song_path : String = "" -- cgit v1.2.3-56-ga3b1