feat(multiplayer): ENet networking + player/world sync + lobby menu + chat

Add dedicated server / host / client modes via NetworkManager autoload,
PlayerSyncComponent (20 Hz unreliable RPC), WorldSyncComponent (authoritative
block break/place), ChatManager (F2), LobbyMenu scene, updated MainMenu
with Solo/Heberger/Rejoindre/Quitter buttons. Port changed to 7777
(9999 occupied by sntlkeyssrvr on this machine). Mobs disabled in multi
(spawn solo only). Solo mode untouched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Floppyrj45
2026-04-19 17:48:48 +02:00
parent 9546fcd96b
commit 5db858527e
15 changed files with 748 additions and 48 deletions

View File

@@ -0,0 +1,132 @@
extends Node
signal connection_succeeded()
signal connection_failed()
signal server_started()
signal server_closed()
signal peer_connected(id: int)
signal peer_disconnected(id: int)
enum Mode { NONE, SOLO, HOST, CLIENT, DEDICATED }
var current_mode: Mode = Mode.NONE
const DEFAULT_PORT := 7777
const MAX_PLAYERS := 16
var peer: ENetMultiplayerPeer = null
func _ready() -> void:
multiplayer.peer_connected.connect(_on_peer_connected)
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
multiplayer.connected_to_server.connect(_on_connection_ok)
multiplayer.connection_failed.connect(_on_connection_failed)
multiplayer.server_disconnected.connect(_on_server_disconnected)
# Auto-start from command line args
var args := OS.get_cmdline_user_args()
if "--server" in args:
start_dedicated_server(DEFAULT_PORT)
elif "--client" in args:
var idx := args.find("--client")
var address := "127.0.0.1"
if idx + 1 < args.size():
address = args[idx + 1]
join_server(address, DEFAULT_PORT)
func start_dedicated_server(port: int = DEFAULT_PORT) -> bool:
peer = ENetMultiplayerPeer.new()
var err := peer.create_server(port, MAX_PLAYERS)
if err != OK:
push_error("NetworkManager: server creation failed — error %d" % err)
peer = null
return false
multiplayer.multiplayer_peer = peer
current_mode = Mode.DEDICATED
print("[NET] Dedicated server listening on port %d" % port)
server_started.emit()
return true
func start_host(port: int = DEFAULT_PORT) -> bool:
peer = ENetMultiplayerPeer.new()
var err := peer.create_server(port, MAX_PLAYERS)
if err != OK:
push_error("NetworkManager: host creation failed — error %d" % err)
peer = null
return false
multiplayer.multiplayer_peer = peer
current_mode = Mode.HOST
print("[NET] Host server listening on port %d" % port)
server_started.emit()
return true
func join_server(address: String, port: int = DEFAULT_PORT) -> bool:
peer = ENetMultiplayerPeer.new()
var err := peer.create_client(address, port)
if err != OK:
push_error("NetworkManager: client connection failed — error %d" % err)
peer = null
return false
multiplayer.multiplayer_peer = peer
current_mode = Mode.CLIENT
print("[NET] Connecting to %s:%d" % [address, port])
return true
func disconnect_from_server() -> void:
if peer != null:
peer.close()
peer = null
multiplayer.multiplayer_peer = null
current_mode = Mode.NONE
server_closed.emit()
func _on_peer_connected(id: int) -> void:
print("[NET] Peer connected: %d" % id)
peer_connected.emit(id)
func _on_peer_disconnected(id: int) -> void:
print("[NET] Peer disconnected: %d" % id)
peer_disconnected.emit(id)
func _on_connection_ok() -> void:
print("[NET] Connected to server (my id: %d)" % multiplayer.get_unique_id())
connection_succeeded.emit()
func _on_connection_failed() -> void:
push_warning("[NET] Connection failed")
peer = null
multiplayer.multiplayer_peer = null
current_mode = Mode.NONE
connection_failed.emit()
func _on_server_disconnected() -> void:
push_warning("[NET] Server disconnected")
peer = null
multiplayer.multiplayer_peer = null
current_mode = Mode.NONE
server_closed.emit()
func is_server() -> bool:
return current_mode == Mode.HOST or current_mode == Mode.DEDICATED
func is_client() -> bool:
return current_mode == Mode.CLIENT
func is_solo() -> bool:
return current_mode == Mode.SOLO or current_mode == Mode.NONE
func get_my_id() -> int:
return multiplayer.get_unique_id()