Chelimbalo/multiplayer/lobby.gd
2025-12-12 18:45:31 +05:00

187 lines
5.1 KiB
GDScript

extends Node
const MAX_PLAYERS: int = 20
const PORT: int = 7777
signal lobby_created
signal lobby_joined
signal lobby_closed
signal update_teams_state
var in_lobby: bool = false
var attack_team: Array[int] = []
var defence_team: Array[int] = []
var specators_team: Array[int] = []
var client_nicknames: Dictionary[int,StringName] = {}
func _ready() -> void:
multiplayer.peer_disconnected.connect(player_left)
multiplayer.server_disconnected.connect(server_disconnected)
multiplayer.peer_connected.connect(add_and_sync_peer)
func _enter_tree() -> void:
pass
func player_left(id: int) -> void:
if attack_team.has(id):
attack_team.erase(id)
elif defence_team.has(id):
defence_team.erase(id)
elif specators_team.has(id):
specators_team.erase(id)
client_nicknames.erase(id)
update_teams_state.emit()
func server_disconnected() -> void:
leave()
func host() -> void:
var peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new()
peer.create_server(PORT,MAX_PLAYERS)
multiplayer.multiplayer_peer = peer
lobby_created.emit()
specators_team.append(multiplayer.get_unique_id())
in_lobby = true
client_nicknames = {1 : ClientSettings.NICKNAME}
func join(ip: String) -> Error:
var peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new()
var res = peer.create_client(ip,PORT)
if res != 0:
return res
multiplayer.multiplayer_peer = peer
lobby_joined.emit()
in_lobby = true
return Error.OK
func leave() -> void:
multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new()
attack_team.clear()
defence_team.clear()
specators_team.clear()
lobby_closed.emit()
in_lobby = false
func add_and_sync_peer(id: int) -> void:
if multiplayer.is_server() == false:
return
specators_team.append(id)
update_teams_state.emit()
set_teams.rpc_id(id,attack_team,defence_team,specators_team)
@rpc("any_peer","call_local","reliable")
func recieve_client_data(data: Dictionary):
if multiplayer.is_server() == false:
return
var id = multiplayer.get_remote_sender_id()
var nickname: StringName = data["nick"].left(16)
client_nicknames[id] = nickname
sync_client_data.rpc(client_nicknames)
@rpc("authority","call_remote")
func sync_client_data(new_client_nicknames: Dictionary[int,StringName]):
if multiplayer.is_server() or multiplayer.get_remote_sender_id() != 1:
return
client_nicknames = new_client_nicknames
@rpc("authority","call_remote","reliable")
func set_teams(attack: Array[int],defence: Array[int],spectators: Array[int]):
attack_team = attack
defence_team = defence
specators_team = spectators
update_teams_state.emit()
if is_multiplayer_authority():
set_teams.rpc(attack,defence,spectators)
func switch_team(team: int) -> void:
team_switch_notification.rpc_id(1,team)
func swap_teams() -> void:
if not is_multiplayer_authority():
return
set_teams(defence_team,attack_team,specators_team)
func shuffle_teams() -> void:
if not is_multiplayer_authority():
return
var peers: Array = Array(multiplayer.get_peers())
peers.append(1)
var new_attack_team: Array[int] = []
var new_defence_team: Array[int] = []
var new_spectator_team: Array[int] = []
while len(new_attack_team) < 5 and len(new_defence_team) < 5:
if len(peers) == 0:
break
var picked_peer = peers.pop_at(randi_range(0,len(peers)-1))
var picked_team = randi_range(0,1)
match picked_team:
Session.TEAMS.DEFENCE:
if len(new_defence_team) < 5:
new_defence_team.append(picked_peer)
else:
new_attack_team.append(picked_peer)
Session.TEAMS.ATTACK:
if len(new_attack_team) < 5:
new_attack_team.append(picked_peer)
else:
new_defence_team.append(picked_peer)
new_spectator_team.append_array(peers)
set_teams(new_attack_team,new_defence_team,new_spectator_team)
@rpc("any_peer","call_local","reliable")
func team_switch_notification(team: int) -> void:
if not is_multiplayer_authority() or (team == Session.TEAMS.DEFENCE and len(defence_team) > 4) or (team == Session.TEAMS.ATTACK and len(attack_team) > 4) or not LobbySettings.allow_team_switch:
return
var id: int = multiplayer.get_remote_sender_id()
if team == Session.TEAMS.DEFENCE:
if attack_team.has(id):
attack_team.erase(id)
if specators_team.has(id):
specators_team.erase(id)
defence_team.append(id)
if team == Session.TEAMS.ATTACK:
if defence_team.has(id):
defence_team.erase(id)
if specators_team.has(id):
specators_team.erase(id)
attack_team.append(id)
if team == Session.TEAMS.SPECTATE:
if attack_team.has(id):
attack_team.erase(id)
elif defence_team.has(id):
defence_team.erase(id)
specators_team.append(id)
update_teams_state.emit()
set_teams.rpc(attack_team,defence_team,specators_team)
func start_game() -> void:
if not multiplayer.is_server():
return
get_tree().current_scene.get_node("%LevelContainer").add_child(Registry.maps[LobbySettings.selected_map].instantiate())
Session.start_session()
func get_team() -> Session.TEAMS:
var id = multiplayer.get_unique_id()
if attack_team.has(id):
return Session.TEAMS.ATTACK
if defence_team.has(id):
return Session.TEAMS.DEFENCE
if specators_team.has(id):
return Session.TEAMS.SPECTATE
return Session.TEAMS.UNASSIGNED