extends Node const MAX_PLAYERS: int = 10 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 validated_players = [] var win_score = 13 var half_rounds = 12 var client_hash: String = "" const CHUNK_SIZE = 1024 func _ready() -> void: multiplayer.peer_disconnected.connect(player_left) multiplayer.server_disconnected.connect(server_disconnected) multiplayer.peer_connected.connect(add_and_sync_peer) multiplayer.connected_to_server.connect(send_validation) var ctx = HashingContext.new() ctx.start(HashingContext.HASH_SHA256) var file = FileAccess.open(OS.get_executable_path(),FileAccess.READ) while file.get_position() < file.get_length(): var remaining = file.get_length() - file.get_position() ctx.update(file.get_buffer(min(remaining,CHUNK_SIZE))) client_hash = ctx.finish().hex_encode() 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) 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 multiplayer.peer_connected.connect(check_player_hash) multiplayer.peer_disconnected.connect(on_player_left) func check_player_hash(id: int): if multiplayer.is_server(): get_tree().create_timer(1).timeout.connect(kick_untrustworthy.bind(id)) func on_player_left(id: int): if multiplayer.is_server(): if validated_players.has(id): validated_players.erase(id) func kick_untrustworthy(id: int): if multiplayer.is_server() and validated_players.has(id) == false: multiplayer.disconnect_peer(id) @rpc("any_peer","call_remote","reliable") func validate_hash(sender_hash: StringName): if multiplayer.is_server() == false: return if client_hash == sender_hash: validated_players.append(multiplayer.get_remote_sender_id()) func send_validation(): validate_hash.rpc_id(1,client_hash) 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: if multiplayer.is_server(): multiplayer.peer_connected.disconnect(check_player_hash) 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_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() func switch_team(team: int) -> void: team_switch_notification.rpc(multiplayer.get_unique_id(),team) @rpc("any_peer","call_local","reliable") func team_switch_notification(id: int, team: int) -> void: if (team == Session.TEAMS.DEFENCE and len(defence_team) > 4) or (team == Session.TEAMS.ATTACK and len(attack_team) > 4): return 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() @rpc("authority","call_local","reliable") func start_game() -> void: get_tree().change_scene_to_file("res://levels/prototype_scene.tscn") if multiplayer.is_server(): await get_tree().scene_changed 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