149 lines
4.2 KiB
GDScript
149 lines
4.2 KiB
GDScript
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()
|