class_name MultiplayerMatchExtension extends MultiplayerAPIExtension var _multiplayer := SceneMultiplayer.new() ## The maximum number of concurrent connections to accept @export_range(1, 4095) var max_peers:int = 32 signal scene_changed func _init() -> void: # Just passthrough base signals (copied to var to avoid cyclic reference) var cs := connected_to_server var cf := connection_failed var pc := peer_connected var pd := peer_disconnected _multiplayer.connected_to_server.connect(cs.emit) _multiplayer.connection_failed.connect(cf.emit) _multiplayer.peer_connected.connect(pc.emit) _multiplayer.peer_disconnected.connect(pd.emit) func _poll() -> Error: return _multiplayer.poll() # Log RPC being made and forward it to the default multiplayer. func _rpc(peer:int, object:Object, method:StringName, args:Array) -> Error: print("Got RPC for %d: %s::%s(%s)" % [peer, object, method, args]) return _multiplayer.rpc(peer, object, method, args) ## Log configuration add. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom. #func _object_configuration_add(object, config: Variant) -> Error: #if config is MultiplayerSynchronizer: #print("Adding synchronization configuration for %s. Synchronizer: %s" % [object, config]) #elif config is MultiplayerSpawner: #print("Adding node %s to the spawn list. Spawner: %s" % [object, config]) #return _multiplayer.object_configuration_add(object, config) # ## Log configuration remove. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom. #func _object_configuration_remove(object, config: Variant) -> Error: #if config is MultiplayerSynchronizer: #print("Removing synchronization configuration for %s. Synchronizer: %s" % [object, config]) #elif config is MultiplayerSpawner: #print("Removing node %s from the spawn list. Spawner: %s" % [object, config]) #return _multiplayer.object_configuration_remove(object, config) # These can be optional, but in our case we want to extend SceneMultiplayer, so forward everything. func _set_multiplayer_peer(p_peer:MultiplayerPeer) -> void: _multiplayer.multiplayer_peer = p_peer func _get_multiplayer_peer() -> MultiplayerPeer: return _multiplayer.multiplayer_peer func _get_unique_id() -> int: return _multiplayer.get_unique_id() func _get_remote_sender_id() -> int: return _multiplayer.get_remote_sender_id() func _get_peer_ids() -> PackedInt32Array: return _multiplayer.get_peers() ## Creates a server peer and listens for connections on all intefaces for specifed [param port] func serve(port:int = 9000) -> Error: var peer:ENetMultiplayerPeer = ENetMultiplayerPeer.new() peer_connected.connect(_on_peer_connected) peer_disconnected.connect(_on_peer_disconnected) var err:Error = peer.create_server(port, max_peers) if err == Error.OK: print("listening for connections on *:%s" % port) _set_multiplayer_peer(peer) return err ## Creates a client peer and connects to specified [param host] and [param port] func join(host:String = "localhost", port:int = 9000) -> void: var peer := ENetMultiplayerPeer.new() peer.create_client(host, port) if peer.get_connection_status() == MultiplayerPeer.CONNECTION_DISCONNECTED: push_error("failed to start multiplayer client") return _set_multiplayer_peer(peer) ## Emitted when a multiplayer peer successfully connects to a server. Only emitted on the server. func _on_peer_connected(peer_id:int) -> void: print("peer `%d` connected" % peer_id) func _on_peer_disconnected(peer_id:int) -> void: print("peer `%d` disconnected" % peer_id)