Files
pirate-dice/scripts/net.gd
2026-09-05 23:19:46 +02:00

137 lines
3.4 KiB
GDScript

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)