class_name LaunchOptions extends RefCounted ## What the command line asks for. Godot passes the arguments after "--": ## --profile=NAME keeps key, save and recordings in a folder of their own, ## so that two windows on one machine are two players ## --name=NAME the player's name; like a name typed in the menu, it is ## remembered for the next start ## --solo starts playing alone at once, without the menu ## --host opens the world for guests at once ## --port=PORT the port an open world listens on ## --join=ADDRESS joins a host at once; ADDRESS may end in ":PORT" ## Longest profile name. const MAX_PROFILE_LENGTH := 32 ## Characters a profile name may contain. const PROFILE_CHARACTERS := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" var profile := "" var player_name := "" ## How to start without the menu: "", "solo", "host" or "join". var start := "" var port := NetLink.DEFAULT_PORT var address := "" ## Arguments that were not understood and are ignored. var ignored := PackedStringArray() ## Reads `arguments`. Unknown arguments and bad values end up in `ignored`. static func parse(arguments: PackedStringArray) -> LaunchOptions: var options := LaunchOptions.new() for argument in arguments: var value := argument.get_slice("=", 1) if argument.contains("=") else "" match argument.get_slice("=", 0): "--profile": if is_valid_profile(value): options.profile = value else: options.ignored.append(argument) "--name": options.player_name = value "--solo": options.start = "solo" "--host": options.start = "host" "--port": if value.is_valid_int() and value.to_int() >= 0 and value.to_int() <= 65535: options.port = value.to_int() else: options.ignored.append(argument) "--join": options.start = "join" options.address = value _: options.ignored.append(argument) return options ## Whether `name` can name a profile folder: up to 32 of the letters A to Z, ## digits, "-" and "_". static func is_valid_profile(name: String) -> bool: if name.is_empty() or name.length() > MAX_PROFILE_LENGTH: return false for character in name: if not PROFILE_CHARACTERS.contains(character): return false return true ## The folder for the player's files. The default profile uses the user ## folder itself, so that saves of earlier versions stay where they are. func storage_dir() -> String: if profile.is_empty(): return "user://" return "user://profiles".path_join(profile)