diff --git a/NOTE.md b/NOTE.md index 65d3e29..27c0922 100644 --- a/NOTE.md +++ b/NOTE.md @@ -3,12 +3,10 @@ A faire : 1. Principal : - Historique + - Paramètres (contenu : fps, volume dans le jeu, plein écran, ...) (bouton dans le jeu) - Documenter (Docstring, README, ...) 2. Visuel : - - Empêcher de spam "se connecter" dans le client (écran d'attente ?) - - Paramètres (contenu : fps, volume dans le jeu, plein écran, ...) (bouton dans le jeu) - - Rendre le texte de status plus visible (fond un peu plus sombre ?) - Changer les images, animations, rajouter les fonds, mettre la musique, ... - Voir les TODOs @@ -17,8 +15,9 @@ A faire : - mode d'emploi (video + pdf) expliquant le fonctionnement Bug : - - (incertain) Dans de rare cas (souvent en fermant brutalement la fenêtre) le processus ne s'arrête pas - + - (incertain) Dans de rare cas (souvent en fermant brutalement la fenêtre) le processus ne s'arrête pas + - Quitter pendant que l'on décide de si l'on doit charger ou non une ancienne sauvegarde fait crash l'adversaire + - Il est possible de se connecter à soi-même si l'on quitte très vite le menu hote vers le menu client Autre : - Tester sur Linux diff --git a/source/event/Listener.py b/source/event/Listener.py index ad013dc..a59a162 100644 --- a/source/event/Listener.py +++ b/source/event/Listener.py @@ -33,5 +33,7 @@ class Listener: :param args: the args of the callbacks :param kwargs: the kwargs of the callbacks """ - for listener in self._events_listener.get(name, set()): + + # .copy() pour que si le listener supprime un de ses événements, la liste de la boucle de change pas de taille + for listener in self._events_listener.get(name, set()).copy(): listener(self, *args, **kwargs) diff --git a/source/gui/scene/RoomJoin.py b/source/gui/scene/RoomJoin.py index 97d2646..c0d8f25 100644 --- a/source/gui/scene/RoomJoin.py +++ b/source/gui/scene/RoomJoin.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from source import network from source.gui.scene.abc import Scene @@ -73,15 +73,39 @@ class RoomJoin(Scene): self.connect.add_listener("on_click_release", self.button_connect) + self.status = self.add_widget( + widget.Text, + x=0.5, y=0.25, + + anchor_x="center", + ) + + self.thread: Optional[network.Client] = None + def button_connect(self, widget, *_): - network.Client( + self.status.text = "Connexion..." + self.status.label.color = (255, 255, 255, 255) # blanc + widget.remove_listener("on_click_release", self.button_connect) + + self.thread = network.Client( window=self.window, + on_connexion_refused=self.connexion_refused, ip_address=self.entry_ip.text, port=int(self.entry_port.text), daemon=True, username=self.entry_username.text - ).start() + ) + self.thread.start() + + def connexion_refused(self): + self.status.text = "Échec de la connexion" + self.status.label.color = (255, 32, 32, 255) # rouge + self.connect.add_listener("on_click_release", self.button_connect) def button_back_callback(self, widget, *_): + if self.thread is not None: self.thread.stop() + from source.gui.scene import MainMenu self.window.set_scene(MainMenu) + + diff --git a/source/network/Client.py b/source/network/Client.py index 3b99c20..357173c 100644 --- a/source/network/Client.py +++ b/source/network/Client.py @@ -1,7 +1,7 @@ import json import socket from pathlib import Path -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any, Optional, Callable from source import path_save from source.gui import scene @@ -12,6 +12,7 @@ from source.utils.thread import in_pyglet_context if TYPE_CHECKING: from source.gui.window import Window + from source.gui.scene import RoomJoin class Client(StoppableThread): @@ -19,10 +20,18 @@ class Client(StoppableThread): The thread executed on the person who join a room. """ - def __init__(self, window: "Window", username: str, ip_address: str, port: int, **kw): + def __init__(self, window: "Window", + username: str, + ip_address: str, + port: int, + on_connexion_refused: Optional[Callable] = None, + **kw): super().__init__(**kw) self.window = window + + self.on_connexion_refused = on_connexion_refused + self.username = username self.ip_address = ip_address self.port = port @@ -31,7 +40,14 @@ class Client(StoppableThread): print("[Client] Thread démarré") with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as connection: - connection.connect((self.ip_address, self.port)) + try: + connection.connect((self.ip_address, self.port)) + except ConnectionRefusedError: + # Appelle l'événement lorsque la connexion échoue + if self.on_connexion_refused is not None: + in_pyglet_context(self.on_connexion_refused) + return + connection.settimeout(5) # défini le timeout à 5 secondes print(f"[Client] Connecté avec {connection}")