class_name GameRoot extends Node signal load_map(name: String) const MAIN_MENU_SCENE := "res://scenes/interface/main_menu/main_menu.tscn" const SERVER_DATA_NODE := "res://scenes/utils/server_data/server_data.tscn" # -- config from args var config_file: String = "" @onready var level_root: Node3D = $Level @onready var utils_root: Node = $Utils func _parse_args() -> void: var args := Array(OS.get_cmdline_args()) var config_arg: String = "--config" if args.has(config_arg): var index := args.find(config_arg) config_file = args[index + 1] # Called when the node enters the scene tree for the first time. func _ready() -> void: _parse_args() var err: Error if err != OK: logger.error("Couldn't load utils node") return if OS.has_feature("dedicated_server") or DisplayServer.get_name() == "headless": err = _start_dedicated_server() if err != OK: logger.error("couldn't start the server, err is " + str(err)) else: err = _start_game() if err != OK: logger.error("couldn't start the game, err is " + str(err)) multiplayer.peer_connected.connect(_on_player_connected) multiplayer.peer_disconnected.connect(_on_player_disconnected) multiplayer.connected_to_server.connect(_on_connected_to_server) func _on_player_disconnected(id) -> void: logger.info("player is disconnected with id: " + str(id)) func _on_player_connected(id) -> void: # Send the client information about the server if multiplayer.is_server(): logger.info("player is connected with id: " + str(id)) _sync_map_from_server.rpc_id(id) @rpc("authority", "reliable", "call_remote") func _sync_map_from_server() -> void: var server_node := helpers.get_server_node() load_map.emit(server_node.current_map) func _on_connected_to_server() -> void: logger.info("connection is successful, sending info") register_player.rpc_id(1, multiplayer.get_unique_id(), "client") @rpc("any_peer", "reliable", "call_remote") func register_player(id: int, name: String): logger.info("registering player: " + str(id)) if multiplayer.is_server(): var player_data := PlayerData.new() player_data.id = id player_data.username = name player_data.active = true var server_node: ServerData = helpers.get_server_node() server_node.players[id] = helpers.player_data_into_dict(player_data) logger.info("player " + str(id) + " is registered") else: logger.debug("register player is supposed to be executed on the server") func _start_dedicated_server() -> Error: if config_file != "": logger.info("reading config from the file: " + config_file) logger.info("starting in the dedicated server mode") return OK func _start_game() -> Error: logger.info("starting in the game mode") if not ResourceLoader.exists(MAIN_MENU_SCENE): return ERR_DOES_NOT_EXIST var scene: PackedScene = ResourceLoader.load(MAIN_MENU_SCENE) if not scene.can_instantiate(): return ERR_CANT_OPEN var node: MainMenu = scene.instantiate() add_child(node) return OK func _load_utils() -> Error: if not ResourceLoader.exists(SERVER_DATA_NODE): return ERR_DOES_NOT_EXIST var scene: PackedScene = ResourceLoader.load(SERVER_DATA_NODE) if not scene.can_instantiate(): return ERR_CANT_OPEN var node: ServerData = scene.instantiate() utils_root.add_child(node) return OK func _on_load_map(map_name: String) -> void: var path_tmpl := "res://scenes/maps/maps/%s" var path := path_tmpl % map_name logger.info("Loading map from " + path) if not ResourceLoader.exists(path): logger.error("map " + map_name + " doesn't exist") var scene: PackedScene = ResourceLoader.load(path) if scene.can_instantiate(): var node: Node3D = scene.instantiate() logger.info("loading map: " + map_name) for c in level_root.get_children(): level_root.remove_child(c) c.queue_free() level_root.add_child(node) else: logger.error("Can't initialize") func create_server( port: int, player_limit: int, server_only: bool = false, map: String = "lowpoly_tdm_2.tscn" ) -> Error: var peer := ENetMultiplayerPeer.new() logger.info("starting a server the port: " + str(port)) var err := peer.create_server(port, player_limit) multiplayer.multiplayer_peer = peer if err: return err _load_utils() var server_data: ServerData = helpers.get_server_node() server_data.port = port server_data.player_limit = player_limit server_data.current_map = map if !server_only: register_player(1, "server") return OK func join_server(ip: String, port: int) -> Error: var peer = ENetMultiplayerPeer.new() logger.info("trying to connect to: " + ip + ":" + str(port)) var err = peer.create_client(ip, port) if err != OK: return err multiplayer.multiplayer_peer = peer return OK