Files
mmo/autoloads/net.gd
Marek Le 2d4002bd3f refactor
2026-05-09 23:37:26 +02:00

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()