diff --git a/p_client.adb b/p_client.adb index 7f7c223..5fc7af0 100644 --- a/p_client.adb +++ b/p_client.adb @@ -63,6 +63,12 @@ package body p_client is procedure deconnexion is -- {} => {Le client se déconnecte du serveur} begin + jeuEnCours := false; + cacherElem(fenetreDeJeu, "valider"); + cacherElem(fenetreDeJeu, "abandon"); + montrerElem(fenetreDeJeu, "finjeu"); + + authenth := false; est_connecte := false; close_socket (socket); end deconnexion; @@ -76,10 +82,11 @@ package body p_client is code := statutMessage(m); case code is when AUTHENTIFICATION_NEEDED => envoyerMessage(c, creerMessageStatut(trim(pseudoClient, BOTH), SEND_NAME)); - when AUTHENTIFICATION_REUSSIE => put_line("Connexion réussie !"); + when AUTHENTIFICATION_REUSSIE => + authenth := true; + statutErreur := -1; when PSEUDO_INCORRECT => - put_line("Le pseudo est déjà utilisé, ou vide."); - authentification(c); + statutErreur := PSEUDO_INCORRECT; when SOLUTION_RESULTAT => decoderMessage(m, code, msg, tailleMsg); effacerGrille(fenetreDeJeu); @@ -100,24 +107,10 @@ package body p_client is chronoJeu.start(fenetreDeJeu); tailleSolution := 0; when FIN_JEU => - jeuEnCours := false; - cacherElem(fenetreDeJeu, "valider"); - cacherElem(fenetreDeJeu, "abandon"); - montrerElem(fenetreDeJeu, "finjeu"); deconnexion; when others => null; end case; end traiterMessage; - procedure authentification(c: in stream_access) is - -- {} => {Authentifie le joueur} - pseudo : string(1..NAME_SIZE); - nb: integer; - begin - put("Entrez votre pseudo : "); - get_line(pseudo, nb); - envoyerMessage(c, creerMessageStatut(pseudo(1..nb), SEND_NAME)); - end authentification; - end p_client; diff --git a/p_client.ads b/p_client.ads index 508ce9a..21235d6 100644 --- a/p_client.ads +++ b/p_client.ads @@ -9,7 +9,10 @@ package p_client is address : sock_addr_type; socket : socket_type; channel : stream_access; + est_connecte : boolean := false; + authenth : boolean := false; + statutErreur : integer := -1; listen : T_Listen; @@ -29,7 +32,4 @@ package p_client is procedure traiterMessage(c: in stream_access; m: in string); -- {} => {Gère un message reçu par le serveur} - - procedure authentification(c: in stream_access); - -- {} => {Authentifie le joueur} end p_client; diff --git a/p_common.adb b/p_common.adb index 098ce3c..ea78487 100644 --- a/p_common.adb +++ b/p_common.adb @@ -1,7 +1,21 @@ +with Ada.Exceptions, Text_IO; +use Ada.Exceptions, Text_IO; + package body p_common is procedure envoyerMessage(c: in stream_access; m: in string) is -- {} => {Envoie un message m à travers c} + begin + if envoyerMessage(c, m) then null; end if; + end envoyerMessage; + + function envoyerMessage(c: in stream_access; m: in string) return boolean is + -- {} => {résultat = true si le message a été envoyé à travers c} begin String'output (c, m); + return true; + exception + when E : others => + put_line("Une erreur " & exception_name(E) & " est survenue lors de l'envoi du message."); + return false; end envoyerMessage; end p_common; diff --git a/p_common.ads b/p_common.ads index 29d9d4f..b8c49c6 100644 --- a/p_common.ads +++ b/p_common.ads @@ -8,4 +8,7 @@ package p_common is procedure envoyerMessage(c: in stream_access; m: in string); -- {} => {Envoie un message m à travers c} + function envoyerMessage(c: in stream_access; m: in string) return boolean; + -- {} => {résultat = true si le message a été envoyé à travers c} + end p_common; diff --git a/p_server.adb b/p_server.adb index c96b013..75de578 100644 --- a/p_server.adb +++ b/p_server.adb @@ -75,7 +75,11 @@ package body p_server is -- {} => {Le message m a été envoyé à tous les joueurs connectés} begin for i in joueurs'range loop - envoyerMessage(joueurs(i).channel, creerMessageStatut(m, code)); + if joueurs(i).connecte then + if not envoyerMessage(joueurs(i).channel, creerMessageStatut(m, code)) then + joueurs(i).connecte := false; + end if; + end if; end loop; end envoyerMessageGlobal; diff --git a/p_server.ads b/p_server.ads index cbe710f..d9e279b 100644 --- a/p_server.ads +++ b/p_server.ads @@ -17,6 +17,7 @@ package p_server is channel : stream_access; listen : T_Listen; + connecte : boolean := true; end record; type TV_Joueurs is array(1..nbJoueurs) of TR_Joueur; diff --git a/p_status.ads b/p_status.ads index 4c499f4..abb259c 100644 --- a/p_status.ads +++ b/p_status.ads @@ -10,6 +10,7 @@ package p_status is SOLUTION_ESSAI: constant integer := 6; SOLUTION_RESULTAT: constant integer := 7; ACTUALISATION_SCORE: constant integer := 8; + VERIFICATION_CONNEXION: constant integer := 9; function creerMessageStatut(msg: in string; statut: in integer) return string; -- {msg est le message à envoyer, statut le code représentant un statut} diff --git a/p_vue_graph.adb b/p_vue_graph.adb index 3ca6fdf..1335073 100644 --- a/p_vue_graph.adb +++ b/p_vue_graph.adb @@ -72,15 +72,22 @@ package body p_vue_graph is obj : FL_OBJECT_Access; begin if getElement(F.PElements, nomElement)=null then - obj := fl_Add_Button(FL_HIDDEN_BUTTON, FL_Coord(x), FL_Coord(y), FL_Coord(largeur), FL_Coord(hauteur), X11.Strings.new_string("")); + obj := fl_Add_Button(FL_HIDDEN_BUTTON, FL_Coord(x), FL_Coord(y), FL_Coord(largeur), FL_Coord(hauteur), X11.Strings.new_string("")); ajoutElement(F.PElements, roundBouton, nomElement, "", "", obj); end if; end ajouterBoutonInvisible; + procedure changerAlignementTexte(f: in out TR_Fenetre; nomElement : in String; alignement : in FL_ALIGN) is + -- {} => {Change l'alignement d'un texte} + P : TA_Element; + begin + P := GetElement(f.PElements, nomElement); + fl_set_object_align(P.Pelement, alignement); + end changerAlignementTexte; + procedure afficherGrille(fen: in out TR_Fenetre; x, y: in natural) is -- {} => {Affiche la grille avec le bord gauche à la position (x, y)} textX, textY: natural; - P : TA_Element; f: p_cases_io.file_type; V: TV_Gaudi(1..16); begin @@ -100,8 +107,7 @@ package body p_vue_graph is ajouterTexte(fen, V(i).nom, trim(Integer'image(V(i).valeur), BOTH), textX, textY, 92, 92); AjouterBoutonInvisible(fen, 'B' & V(i).nom, textX, textY, 92, 92); -- Rend les nombres cliquables, sans voir de bouton changerTailleTexte(fen, V(i).nom, FL_HUGE_SIZE); - P := GetElement(fen.PElements, V(i).nom); - fl_set_object_align(P.Pelement, FL_ALIGN_CENTER); -- On centre le texte + changerAlignementTexte(fen, V(i).nom, FL_ALIGN_CENTER); end loop; end afficherGrille; @@ -186,10 +192,13 @@ package body p_vue_graph is ajouterTexte(fenetre, "Score", "0 Point", 170, 50, 120, 30); ajouterTexte(fenetre, "Txt2", "Temps : ", 300, 50, 80, 30); ajouterTexte(fenetre, "Timer", Integer'image(Integer(Float'rounding(Float(tempsRestant)))), 380, 50, 80, 30); + ajouterTexte(fenetre, "erreur", "", 50, 640, 400, 30); ajouterChamp(fenetre, "SolutionProp", "", "", 100, 520, 300, 30); ajouterBouton(fenetre, "valider", "Valider", 200, 560, 100, 30); ajouterBouton(fenetre, "finjeu", "Fin Jeu", 200, 600, 100, 30); ajouterBouton(fenetre, "abandon", "Abandonner", 200, 650, 100, 30); + changerCouleurTexte(fenetre, "erreur", FL_INDIANRED); + changerStyleTexte(fenetre, "erreur", FL_BOLD_STYLE); changerStyleTexte(fenetre, "SolutionProp", FL_BOLD_STYLE); changerStyleTexte(fenetre, "valider", FL_BOLD_STYLE); changerStyleTexte(fenetre, "finjeu", FL_BOLD_STYLE); @@ -202,6 +211,8 @@ package body p_vue_graph is changerTailleTexte(fenetre, "finjeu", FL_MEDIUM_SIZE); changerTailleTexte(fenetre, "Txt1", FL_MEDIUM_SIZE); changerTailleTexte(fenetre, "Txt2", FL_MEDIUM_SIZE); + changerTailleTexte(fenetre, "erreur", FL_MEDIUM_SIZE); + changerAlignementTexte(fenetre, "erreur", FL_ALIGN_CENTER); cacherElem(fenetre, "finjeu"); @@ -314,38 +325,63 @@ package body p_vue_graph is ajouterTexte(fenetre, "Text3 : ", "Port serveur : ", 50, 150, 150, 30); ajouterChamp(fenetre, "port", "", "", 200, 150, 160, 30); + ajouterTexte(fenetre, "erreur", "", 50, 200, 400, 30); + changerCouleurTexte(fenetre, "erreur", FL_INDIANRED); + changerStyleTexte(fenetre, "erreur", FL_BOLD_STYLE); + ajouterBouton(fenetre, "valider", "Valider", 200, 300, 100, 30); finFenetre(fenetre); montrerFenetre(fenetre); loop - declare - nomBouton : string := attendreBouton(fenetre); - pseudo : string := consulterContenu(fenetre, "pseudo"); - adresse : string := consulterContenu(fenetre, "serveur"); - port : string := consulterContenu(fenetre, "port"); - begin - if pseudo'length > 20 then - changerContenu(fenetre, "pseudo", ""); - elsif pseudo'length = 0 or adresse'length = 0 or port'length = 0 then null; - elsif port'length > 5 then - changerContenu(fenetre, "port", ""); - elsif nomBouton = "valider" then - pseudoClient := (others => ' '); - pseudoClient(1..pseudo'length) := pseudo; - exit; + loop + declare + nomBouton : string := attendreBouton(fenetre); + pseudo : string := consulterContenu(fenetre, "pseudo"); + adresse : string := consulterContenu(fenetre, "serveur"); + port : string := consulterContenu(fenetre, "port"); + begin + if pseudo'length > 20 then + changerContenu(fenetre, "pseudo", ""); + elsif port'length > 5 then + changerContenu(fenetre, "port", ""); + elsif pseudo'length = 0 or adresse'length = 0 or port'length = 0 then null; + else + pseudoClient := (others => ' '); + pseudoClient(1..pseudo'length) := pseudo; + exit; + end if; + end; + end loop; + + if est_connecte then + statutErreur := -1; + if not envoyerMessage(channel, creerMessageStatut(trim(pseudoClient, BOTH), SEND_NAME)) then + cacherFenetre(fenetre); + fenetreAccueil; + return; end if; - end; - end loop; + end if; + while (nbEssai <= 10 and not est_connecte) + and then not connexion(consulterContenu(fenetre, "serveur"), Integer'value(consulterContenu(fenetre, "port"))) loop + nbEssai := nbEssai + 1; + if nbEssai = 10 then + cacherFenetre(fenetre); + fenetreAccueil; + return; + end if; + end loop; - while nbEssai <= 10 and not connexion(consulterContenu(fenetre, "serveur"), Integer'value(consulterContenu(fenetre, "port"))) loop - nbEssai := nbEssai + 1; - if nbEssai = 10 then - cacherFenetre(fenetre); - fenetreAccueil; - return; + while statutErreur = -1 and not authenth loop + delay 0.1; + end loop; + + if statutErreur = PSEUDO_INCORRECT then + changerTexte(fenetre, "erreur", "Le pseudo est incorrect."); end if; + + exit when statutErreur = -1; end loop; cacherFenetre(fenetre); @@ -515,7 +551,10 @@ package body p_vue_graph is changerContenu(fenetre, "SolutionProp", ""); if enLigne then if solution'length <= 14 and solution'length >= 6 then - envoyerMessage(channel, creerMessageStatut(solution, SOLUTION_ESSAI)); + if not envoyerMessage(channel, creerMessageStatut(solution, SOLUTION_ESSAI)) then + changerTexte(fenetre, "erreur", "La communication avec le serveur a ete interrompue"); + deconnexion; + end if; appuiBoutonJeu(attendreBouton(fenetre), fenetre); else appuiBoutonJeu(attendreBouton(fenetre), fenetre); diff --git a/p_vue_graph.ads b/p_vue_graph.ads index 28186c9..3ea0c50 100644 --- a/p_vue_graph.ads +++ b/p_vue_graph.ads @@ -23,6 +23,9 @@ package p_vue_graph is x, y : in Natural; largeur, hauteur : in Positive); -- {} => {Ajoute un bouton qui n'est pas visible mais est cliquable à l'écran} + procedure changerAlignementTexte(f: in out TR_Fenetre; nomElement : in String; alignement : in FL_ALIGN); + -- {} => {Change l'alignement d'un texte} + procedure afficherGrille(fen: in out TR_Fenetre; x,y: in natural); -- {} => {Affiche la grille avec le bord gauche à la position (x,y)} diff --git a/server.adb b/server.adb index 35b1364..9c13ea9 100644 --- a/server.adb +++ b/server.adb @@ -63,8 +63,14 @@ begin envoyerMessage(joueurs(i).channel, creerMessageStatut("", AUTHENTIFICATION_NEEDED)); joueurs(i).name := (others => ' '); - while joueurs(i).name = EMPTY_NAME loop + end loop; + + for i in joueurs'range loop + while joueurs(i).name = EMPTY_NAME and joueurs(i).connecte loop delay 0.5; + if not envoyerMessage(joueurs(i).channel, creerMessageStatut("", VERIFICATION_CONNEXION)) then + joueurs(i).connecte := false; + end if; end loop; end loop;