feat: Introduce a comprehensive game lobby system including UI, room management, and player interactions.
This commit is contained in:
@@ -38,8 +38,12 @@ var available_rooms: Array = []
|
||||
var is_host: bool = false
|
||||
var is_lan_mode: bool = false # True when using direct ENet (no Nakama)
|
||||
const LAN_PORT: int = 7777 # Port for LAN direct connections
|
||||
const LAN_DISCOVERY_PORT: int = 7778 # Port for LAN discovery
|
||||
var local_player_name: String = "Player"
|
||||
|
||||
var _udp_peer: PacketPeerUDP
|
||||
var _broadcast_timer: Timer
|
||||
|
||||
# Match duration in seconds (configurable in lobby by host)
|
||||
var match_duration: int = 180 # Default 3 minutes
|
||||
|
||||
@@ -93,12 +97,35 @@ var _all_ready: bool = false
|
||||
func _ready():
|
||||
_update_available_areas(game_mode)
|
||||
|
||||
# Setup UDP for LAN discovery
|
||||
_udp_peer = PacketPeerUDP.new()
|
||||
|
||||
# Connect to Nakama signals
|
||||
NakamaManager.match_joined.connect(_on_match_joined)
|
||||
multiplayer.peer_connected.connect(_on_peer_connected)
|
||||
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
|
||||
multiplayer.server_disconnected.connect(_on_server_disconnected)
|
||||
|
||||
func _process(_delta):
|
||||
_listen_for_lan_discovery()
|
||||
|
||||
func _listen_for_lan_discovery():
|
||||
if not _udp_peer or not is_lan_mode or is_host: return
|
||||
if not _udp_peer.is_bound(): return
|
||||
|
||||
while _udp_peer.get_available_packet_count() > 0:
|
||||
var packet = _udp_peer.get_packet()
|
||||
var ip = _udp_peer.get_packet_ip()
|
||||
var data_str = packet.get_string_from_utf8()
|
||||
|
||||
if not data_str.begins_with("TEKTON_HOST:"): continue
|
||||
|
||||
var room_info_json = data_str.trim_prefix("TEKTON_HOST:")
|
||||
var room_info = JSON.parse_string(room_info_json)
|
||||
if room_info is Dictionary:
|
||||
room_info["ip"] = ip
|
||||
_update_lan_room_list(room_info)
|
||||
|
||||
func _update_available_areas(mode: String) -> void:
|
||||
match mode:
|
||||
"Freemode":
|
||||
@@ -179,9 +206,55 @@ func create_room_lan(room_name: String = "LAN Game") -> bool:
|
||||
})
|
||||
|
||||
print("[LAN] Server created on port %d. Waiting for players..." % LAN_PORT)
|
||||
_start_lan_broadcast(room_name)
|
||||
emit_signal("room_joined", current_room)
|
||||
return true
|
||||
|
||||
func _start_lan_broadcast(room_name: String):
|
||||
_stop_lan_broadcast()
|
||||
if _udp_peer.bind(0) != OK:
|
||||
push_error("[LAN] Failed to bind UDP for broadcasting")
|
||||
return
|
||||
_udp_peer.set_broadcast_enabled(true)
|
||||
|
||||
_broadcast_timer = Timer.new()
|
||||
_broadcast_timer.name = "LANBroadcastTimer"
|
||||
_broadcast_timer.wait_time = 2.0
|
||||
_broadcast_timer.autostart = true
|
||||
add_child(_broadcast_timer)
|
||||
_broadcast_timer.timeout.connect(_broadcast_lan_room.bind(room_name))
|
||||
|
||||
func _broadcast_lan_room(room_name: String):
|
||||
var room_data = {
|
||||
"room_name": room_name,
|
||||
"host_name": local_player_name,
|
||||
"player_count": players_in_room.size(),
|
||||
"max_players": GameStateManager.max_players,
|
||||
"match_id": "LAN"
|
||||
}
|
||||
var msg = "TEKTON_HOST:" + JSON.stringify(room_data)
|
||||
_udp_peer.set_dest_address("255.255.255.255", LAN_DISCOVERY_PORT)
|
||||
_udp_peer.put_packet(msg.to_utf8_buffer())
|
||||
|
||||
func _stop_lan_broadcast():
|
||||
if _broadcast_timer:
|
||||
_broadcast_timer.stop()
|
||||
_broadcast_timer.queue_free()
|
||||
_broadcast_timer = null
|
||||
if _udp_peer and _udp_peer.is_bound():
|
||||
_udp_peer.close()
|
||||
|
||||
func _update_lan_room_list(room_info: Dictionary):
|
||||
var found = false
|
||||
for i in range(available_rooms.size()):
|
||||
if available_rooms[i].get("ip") == room_info["ip"]:
|
||||
available_rooms[i] = room_info
|
||||
found = true
|
||||
break
|
||||
if not found:
|
||||
available_rooms.append(room_info)
|
||||
emit_signal("room_list_updated", available_rooms)
|
||||
|
||||
func join_room_lan(host_ip: String) -> bool:
|
||||
"""Client joins a LAN room by the host's IP address. No Nakama/Docker required."""
|
||||
is_host = false
|
||||
@@ -215,6 +288,7 @@ func leave_room() -> void:
|
||||
|
||||
# Important: Reset all lobby settings and player lists first
|
||||
reset()
|
||||
_stop_lan_broadcast()
|
||||
|
||||
if is_lan_mode:
|
||||
# LAN mode: just close the ENet peer directly
|
||||
@@ -231,7 +305,16 @@ func leave_room() -> void:
|
||||
emit_signal("room_left")
|
||||
|
||||
func refresh_room_list() -> void:
|
||||
"""Request updated room list from Nakama."""
|
||||
"""Request updated room list from Nakama or scan for LAN rooms."""
|
||||
if is_lan_mode:
|
||||
available_rooms.clear()
|
||||
if _udp_peer.is_bound(): _udp_peer.close()
|
||||
var err = _udp_peer.bind(LAN_DISCOVERY_PORT)
|
||||
if err != OK:
|
||||
push_error("[LAN] Failed to bind to discovery port %d" % LAN_DISCOVERY_PORT)
|
||||
emit_signal("room_list_updated", available_rooms)
|
||||
return
|
||||
|
||||
if not NakamaManager.is_connected_to_nakama():
|
||||
var success = await NakamaManager.connect_to_nakama_async()
|
||||
if not success:
|
||||
|
||||
Reference in New Issue
Block a user