extends Node const DEFAULT_PORT: int = 7777 const MAX_PLAYERS: int = 4 signal peer_connected(id: int) signal peer_disconnected(id: int) signal connected_to_server() signal connection_failed() signal server_disconnected() signal world_ready() signal peer_world_loaded(peer_id: int) var player_names: Dictionary = {} var local_name: String = "Player" var _expected_peers: Array = [] var _ready_peers: Array = [] func _ready() -> void: multiplayer.peer_connected.connect(_on_peer_connected) multiplayer.peer_disconnected.connect(_on_peer_disconnected) multiplayer.connected_to_server.connect(_on_connected_to_server) multiplayer.connection_failed.connect(_on_connection_failed) multiplayer.server_disconnected.connect(_on_server_disconnected) func host(port: int = DEFAULT_PORT, max_clients: int = MAX_PLAYERS - 1) -> bool: var peer := ENetMultiplayerPeer.new() var err := peer.create_server(port, max_clients) if err != OK: push_error("Net: failed to host on port %d (err=%d)" % [port, err]) return false multiplayer.multiplayer_peer = peer player_names[1] = local_name return true func join(address: String, port: int = DEFAULT_PORT) -> bool: var peer := ENetMultiplayerPeer.new() var err := peer.create_client(address, port) if err != OK: push_error("Net: failed to join %s:%d (err=%d)" % [address, port, err]) return false multiplayer.multiplayer_peer = peer return true func host_singleplayer() -> bool: if multiplayer.multiplayer_peer != null: multiplayer.multiplayer_peer.close() var peer := OfflineMultiplayerPeer.new() multiplayer.multiplayer_peer = peer player_names.clear() player_names[1] = local_name return true func disconnect_net() -> void: if multiplayer.multiplayer_peer != null: multiplayer.multiplayer_peer.close() multiplayer.multiplayer_peer = null player_names.clear() func is_host() -> bool: return multiplayer.multiplayer_peer == null or multiplayer.is_server() func is_authority_for(node: Node) -> bool: return node.is_multiplayer_authority() func local_id() -> int: if multiplayer.multiplayer_peer == null: return 1 return multiplayer.get_unique_id() func _on_peer_connected(id: int) -> void: peer_connected.emit(id) if is_host(): _register_name.rpc_id(id, 1, local_name) func _on_peer_disconnected(id: int) -> void: player_names.erase(id) peer_disconnected.emit(id) func _on_connected_to_server() -> void: player_names[1] = "Host" player_names[multiplayer.get_unique_id()] = local_name _register_name.rpc(multiplayer.get_unique_id(), local_name) connected_to_server.emit() func _on_connection_failed() -> void: multiplayer.multiplayer_peer = null connection_failed.emit() func _on_server_disconnected() -> void: multiplayer.multiplayer_peer = null player_names.clear() server_disconnected.emit() @rpc("any_peer", "reliable", "call_local") func _register_name(peer_id: int, name: String) -> void: player_names[peer_id] = name func mark_world_loaded() -> void: if multiplayer.multiplayer_peer == null: _expected_peers = [1] _ready_peers = [1] world_ready.emit() return if is_host(): _expected_peers = [1] for p in multiplayer.get_peers(): _expected_peers.append(p) _ready_peers = [1] if _all_ready(): _broadcast_ready.rpc() else: _client_world_loaded.rpc_id(1, multiplayer.get_unique_id()) @rpc("any_peer", "reliable") func _client_world_loaded(peer_id: int) -> void: if not is_host(): return if not peer_id in _expected_peers: _expected_peers.append(peer_id) if not peer_id in _ready_peers: _ready_peers.append(peer_id) peer_world_loaded.emit(peer_id) if _all_ready(): _broadcast_ready.rpc() @rpc("authority", "reliable") func _load_scene_for_peer(path: String) -> void: GameState.change_scene(path) func tell_peer_to_load_scene(peer_id: int, path: String) -> void: if not is_host(): return _load_scene_for_peer.rpc_id(peer_id, path) @rpc("authority", "reliable", "call_local") func _broadcast_ready() -> void: world_ready.emit() func _all_ready() -> bool: for p in _expected_peers: if not p in _ready_peers: return false return true func reset_world_ready() -> void: _expected_peers.clear() _ready_peers.clear()