# This file is part of open-fpsz. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . class_name Multiplayer extends Node @export_category("Parameters") @export var PLAYER : PackedScene @export var FLAG : PackedScene @export var MAX_CLIENTS : int = 24 @export var RESPAWN_TIME : float = 3.0 @onready var players : Node = $Players @onready var objectives : Node = $Objectives @onready var map : Node = $Map @onready var scoreboard : Scoreboard = $Scoreboard signal connected_to_server signal connection_failed func start_server(port : int, map_scene : PackedScene, nickname : String = "mercury") -> void: # setup enet server peer var peer : ENetMultiplayerPeer = ENetMultiplayerPeer.new() peer.create_server(port, MAX_CLIENTS) multiplayer.peer_disconnected.connect(remove_player) multiplayer.multiplayer_peer = peer _load_map(map_scene) if DisplayServer.get_name() != "headless": add_player(1, nickname) func join_server(host : String, port : int, nickname : String) -> void: var peer : ENetMultiplayerPeer = ENetMultiplayerPeer.new() peer.create_client(host, port) multiplayer.connected_to_server.connect(_on_connected_to_server.bind(nickname)) multiplayer.connection_failed.connect(_on_connection_failed) multiplayer.multiplayer_peer = peer func _on_connected_to_server(nickname : String) -> void: connected_to_server.emit() scoreboard.request_scoreboard_from_authority.rpc() _join_match.rpc(nickname) func _on_connection_failed() -> void: connection_failed.emit() func _on_player_died(player : Player, _killer_id : int) -> void: await get_tree().create_timer(RESPAWN_TIME).timeout respawn_player(player) func respawn_player(player : Player) -> void: var spawn_location : Vector3 = MapsManager.get_player_spawn().position player.respawn.rpc(spawn_location) func add_player(peer_id : int, nickname : String) -> void: var player : Player = PLAYER.instantiate() player.name = str(peer_id) player.died.connect(_on_player_died) players.add_child(player) player.match_participant_component.player_id = peer_id player.match_participant_component.team_id = ($RabbitScoringComponent as RabbitScoringComponent)._team_chasers.team_id player.match_participant_component.nickname = nickname player.global_position = MapsManager.get_player_spawn().position $DeathmatchScoringComponent.subscribe_player(player) scoreboard.add_participant(player.match_participant_component) print("Peer `%s` connected" % player.name) func remove_player(peer_id : int) -> void: var node_name : String = str(peer_id) if players.has_node(node_name): var player : Player = players.get_node(node_name) scoreboard.remove_participant(player.match_participant_component) player.died.disconnect(_on_player_died) $DeathmatchScoringComponent.unsubscribe_player(player) player.queue_free() print("Peer `%s` disconnected" % node_name) func _load_map(scene : PackedScene) -> void: var map_scene : Node = scene.instantiate() MapsManager.current_map = map_scene map_scene.ready.connect(_add_flag) map.add_child(map_scene) func _add_flag() -> void: var flag : Flag = FLAG.instantiate() $RabbitScoringComponent.setup(flag) objectives.add_child(flag) var flagstand : Marker3D = MapsManager.current_map.get_node("FlagStand") if flagstand: flag.global_position = flagstand.global_position @rpc("any_peer", "reliable") func _join_match(nickname : String) -> void: if is_multiplayer_authority(): add_player(multiplayer.get_remote_sender_id(), nickname) func _exit_tree() -> void: if is_multiplayer_authority(): multiplayer.peer_disconnected.disconnect(remove_player) multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new()