137 lines
3.4 KiB
GDScript
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)
|