extends Node ## Netzwerk-Verwaltung: Host/Client via ENet, Lobby und Spielstart. signal lobby_changed signal game_started(config: Dictionary) signal connection_failed(reason: String) signal server_closed const PORT := 8910 const MAX_HUMANS := 8 var player_name := "Spieler" ## peer_id -> name (enthält auch den Host mit id 1) var lobby: Dictionary = {} var is_host := false var in_game := false func _ready() -> void: multiplayer.peer_connected.connect(_on_peer_connected) multiplayer.peer_disconnected.connect(_on_peer_disconnected) multiplayer.connected_to_server.connect(_on_connected) multiplayer.connection_failed.connect(_on_connect_fail) multiplayer.server_disconnected.connect(_on_server_disconnected) func host_game(pname: String, port: int = PORT) -> bool: player_name = pname var peer := ENetMultiplayerPeer.new() var err := peer.create_server(port, MAX_HUMANS - 1) if err != OK: connection_failed.emit("Server konnte nicht gestartet werden (Port %d belegt?)" % port) return false multiplayer.multiplayer_peer = peer is_host = true lobby = {1: pname} lobby_changed.emit() return true func join_game(ip: String, pname: String, port: int = PORT) -> bool: player_name = pname var peer := ENetMultiplayerPeer.new() var err := peer.create_client(ip, port) if err != OK: connection_failed.emit("Verbindung zu %s:%d fehlgeschlagen" % [ip, port]) return false multiplayer.multiplayer_peer = peer is_host = false return true func leave() -> void: if multiplayer.multiplayer_peer != null: multiplayer.multiplayer_peer.close() multiplayer.multiplayer_peer = null lobby.clear() is_host = false in_game = false lobby_changed.emit() func is_online() -> bool: var peer := multiplayer.multiplayer_peer return peer is ENetMultiplayerPeer \ and peer.get_connection_status() != MultiplayerPeer.CONNECTION_DISCONNECTED func _on_peer_connected(id: int) -> void: if is_host: _push_lobby.rpc_id(id, lobby) func _on_peer_disconnected(id: int) -> void: if is_host: lobby.erase(id) _push_lobby.rpc(lobby) lobby_changed.emit() func _on_connected() -> void: _register.rpc_id(1, player_name) func _on_connect_fail() -> void: multiplayer.multiplayer_peer = null connection_failed.emit("Server nicht erreichbar.") func _on_server_disconnected() -> void: multiplayer.multiplayer_peer = null lobby.clear() in_game = false server_closed.emit() @rpc("any_peer", "reliable") func _register(pname: String) -> void: if not is_host: return var id := multiplayer.get_remote_sender_id() lobby[id] = pname.substr(0, 16) _push_lobby.rpc(lobby) lobby_changed.emit() @rpc("authority", "reliable") func _push_lobby(data: Dictionary) -> void: lobby = data lobby_changed.emit() ## Einzelspieler: kein Netzwerk, nur der lokale Spieler und Bots. func start_singleplayer(pname: String, ai_count: int) -> void: player_name = pname multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new() is_host = true lobby = {1: pname} lobby_changed.emit() _begin({"peers": [1], "names": lobby.duplicate(), "ai": ai_count}) ## Nur der Host ruft das auf. func start_game(ai_count: int) -> void: if not is_host: return var order: Array = lobby.keys() order.sort() var cfg := {"peers": order, "names": lobby.duplicate(), "ai": ai_count} _begin.rpc(cfg) @rpc("authority", "call_local", "reliable") func _begin(cfg: Dictionary) -> void: in_game = true game_started.emit(cfg)