Package reseau.jeu.serveur

Source Code of reseau.jeu.serveur.JoueurDistant

/*
  Copyright (C) 2010 Aurelien Da Campo, Pierre-Dominique Putallaz
 
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

package reseau.jeu.serveur;

import java.io.IOException;

import models.joueurs.Joueur;

import org.json.JSONException;
import org.json.JSONObject;

import outils.Configuration;
import reseau.CanalTCP;
import reseau.CanalException;
import reseau.Port;

/**
* Une classe qui modélise coté serveur un joueur.
*
* @author Pierre-Dominique Putallaz
* @author Da Campo Aurélien
*/
public class JoueurDistant implements Runnable, ConstantesServeurJeu
{
  // Constantes pour les états de la connexion avec le joueur distant
  private final static int EN_ATTENTE = 0;
  private final static int VALIDATION = 1;
  private final static int EN_JEU = 2;
  private final static int EN_PAUSE = 3;
  private final static int QUITTE = 4;
  private final static int PARTIE_TERMINEE = 5;

  /**
   * Canal de dialogue commun
   */
  private CanalTCP canal;
 
  /**
   * Canal de mise à jour
   */
  private CanalTCP canal_update;
 
  /**
   * identificateur du jeu
   */
  private Joueur joueur;
 
  /**
   * Serveur de jeu
   */
  private ServeurJeu serveur;
 
  /**
   * Etat (initialement en validation)
   */
  private int etat = VALIDATION;
 
  /**
   * Message du client;
   */
  private String str = "";
 
  /**
   * Offset pour les ports temporaires
   */
  private static int offset_port = Configuration.getPortSJ_JD();

  /**
   * Niveau d'affichage des messages
   */
  public static boolean verbeux = false;

  /**
   * Crée un lien avec un joueur distant.
   *
   * @param ID
   *            L'ID associée au joueur.
   * @param canal
   *            Le canal de communication.
   * @param serveur
   *            Le serveur de jeu associé au joueur.
   */
  public JoueurDistant(Joueur joueur, CanalTCP canal, ServeurJeu serveur)
  {
    this.canal    = canal;
    this.joueur   = joueur;
    this.serveur  = serveur;

    log("Nouveau client +"+joueur.getId());
    (new Thread(this)).start();
  }

  @Override
  protected void finalize() throws Throwable
  {
    // En cas de déréférencement de l'objet, on aura tendance à couper le
    // canal de communication
    fermerCanal();
  }

  /**
   * Tache d'écoute du canal
   */
  public void run()
  {
    while (true)
    {
      try
      {
        actionsEtats();
      }
      catch (JSONException e)
      {
        logErreur("Récéption inconnue \"" + str + "\"",e);
      }
      catch (CanalException e) {
         
          serveur.joueurDeconnecte(joueur);
         
          logErreur("Canal erroné \"" + str + "\"",e);
                return;
            }
      catch (IOException e)
            {
          serveur.joueurDeconnecte(joueur);
         
          logErreur("ERROR : canal erroné \"" + str + "\"",e);
                return;
            }
    }
  }

  /**
   * Ecoute un message du client.
   *
   * @return Une chaine de caractère.
   * @throws CanalException
   */
  private String attendreMessage() throws CanalException
  {
    // Récéption du message du client
    synchronized (canal)
    {
      str = canal.recevoirString();
      log("Récéption de " + str);
      return str;
    }
  }
 
  /**
   * Machine d'état du client
   *
   * @throws JSONException
   *             Erreur levée si la chaine de caractère reçu du serveur n'est
   *             pas un format JSON
   * @throws CanalException
   * @throws IOException
   */
  private void actionsEtats() throws JSONException, CanalException, IOException
  {
    log("Etat : " + getNomEtat(etat));

    switch (etat)
      {
          case VALIDATION:
              actionsEtatValidation();                  
            break;
         
          case EN_ATTENTE:
            actionsEtatEnAttente();
            break;
         
          case EN_JEU:
              actionsEtatEnJeu();
              break;
          default:
            logErreur("Etat inconnu",null);
    }
  }

  private void actionsEtatValidation() throws CanalException, IOException
    {
      // Envoi de la version du serveur au client
        envoyer(ServeurJeu.VERSION);
       
        // Réservation du port pour le canal temporaire
        Port port = new Port(offset_port++);
        port.reserver();
       
        // Envoi du numéro de port utilisé
        envoyer(port.getNumeroPort());
       
        // Création du canal de mise à jour et attente de la connexion
        log("Création du canal de synchronisation");
       
        // Création du canal
        canal_update = new CanalTCP(port);
   
        log("Canal crée");
       
        // envoie de l'etat de la partie
        envoyerSurCanalMAJ(Protocole.construireMsgJoueursEtat(serveur.getJoueurs()));
       
        // Passage en état EN_ATTENTE
        etat = EN_ATTENTE;
    }

    /**
   * Attente
   *
   * @throws JSONException
   * @throws CanalException
   */
  private void actionsEtatEnAttente() throws JSONException, CanalException
    {
      // Attente d'un message
        JSONObject json = new JSONObject(attendreMessage());
       
        // Extraction du type du message
        int type = json.getInt("TYPE");
        log("Récéption d'un message de type " + type + " dans l'état : "+ etat);
       
        switch (type)
        {
            // Récéption d'un message texte
            case JOUEUR_MESSAGE:
                receptionMsgDemandeEnvoieMessage(json);
                break;   
       
            // Changement d'equipe
            case JOUEUR_CHANGER_EQUIPE:
                receptionMsgChangementEquipe(json);
                break;
               
             // Changement d'equipe
            case JOUEUR_PRET:
               
                log("Entre en jeu");
                etat = EN_JEU;
                break;
               
            // deconnexion
            case JOUEUR_DECONNEXION:
               
                log("Terminaison de la liaison avec le client");
               
                // On supprime le joueur distant de la liste des clients
                serveur.joueurDeconnecte(joueur);
               
                // On clos la liaison avec le client
                fermerCanal();
               
                break;     
        }
    }

    private void receptionMsgChangementEquipe(JSONObject json) throws CanalException, JSONException
    {
        int idEquipe = json.getInt("ID_EQUIPE");
        int idJoueur2 = json.getInt("ID_JOUEUR");
       
        // joueur identique ou admin
        if(idJoueur2 == joueur.getId() || joueur.getId() == serveur.getIdCreateur())
            envoyer(serveur.changerEquipe(idJoueur2,idEquipe));
        else
            repondreEtat(JOUEUR_CHANGER_EQUIPE, ACTION_NON_AUTORISEE);
    }

    /**
   * Envoi un message au client
   *
   * @param msg
   *            Le message à envoyer.
   * @throws CanalException
   */
  public synchronized void envoyer(final String msg) throws CanalException
  {
    log("Envoi du String " + msg);
    canal.envoyerString(msg);
  }

  public synchronized void envoyer(final int msg) throws CanalException
  {
    synchronized (canal)
    {
      log("Envoi de l'int " + msg);
      canal.envoyerInt(msg);
    }
  }

  private void actionsEtatEnJeu() throws JSONException, CanalException
  {
    // Attente d'un message
    JSONObject json = new JSONObject(attendreMessage());
   
    // Extraction du type du message
    int type = json.getInt("TYPE");
   
    log("Récéption d'un message de type " + type + " dans l'état : "+ etat);
   
    switch (type)
    {
        // Récéption d'un message texte
        case JOUEUR_MESSAGE:
            receptionMsgDemandeEnvoieMessage(json);
          break;
       
        // Action sur une vague
        case VAGUE:
            receptionMsgDemandeLancementVague(json);
          break;
         
        // Requête de création d'une tour
        case TOUR_AJOUT:
            receptionMsgDemandeAjoutTour(json);
          break;
         
        // Requête d'amélioration d'une tour
        case TOUR_AMELIORATION:
            receptionMsgDemandeAmeliorerTour(json);
          break;
         
        // Requete de suppresion d'une tour
        case TOUR_SUPRESSION:
          receptionMsgDemandeSuppressionTour(json);
          break;
         
        // deconnexion
            case JOUEUR_DECONNEXION:
               
                log("Terminaison de la liaison avec le client");
               
                // On supprime le joueur distant de la liste des clients
                serveur.joueurDeconnecte(joueur);
               
                // On clos la liaison avec le client
                fermerCanal();
               
                break;
         
        default:
          logErreur("Type de message inconnu : " + type,null);
          // Signaler au client qu'il envoi quelque chose d'incorecte
          repondreEtat(ERREUR, ERREUR);
          break;
        }
  }

    private void receptionMsgDemandeSuppressionTour(JSONObject json) throws JSONException, CanalException
    {
      // Récupération de la tour cible
        int tourCibleDel = json.getInt("ID_TOWER");
        // Demande au serveur de l'opération
        int code = serveur.vendreTour(joueur, tourCibleDel);
        // Retour au client de code
        repondreEtat(TOUR_SUPRESSION, code);
    }

    private void receptionMsgDemandeAmeliorerTour(JSONObject json) throws JSONException, CanalException
    {
      // Récupération de la tour cible
        int tourCible = json.getInt("ID_TOWER");
        // Demande au serveur de l'opération
        int code = serveur.ameliorerTour(joueur, tourCible);
        // Retour au client de code
        repondreEtat(TOUR_AMELIORATION, code);
    }

    private void receptionMsgDemandeAjoutTour(JSONObject json) throws JSONException, CanalException
    {
        // Extraction des coordonnées
        int x = json.getInt("X");
        int y = json.getInt("Y");
        // Extraction du type de tour
        int typeTour = json.getInt("TYPE_TOUR");
       
        // Demande d'ajout au serveur
        int code = serveur.poserTour(joueur, typeTour, x, y);
        // Retour au client du code
        repondreEtat(TOUR_AJOUT, code);
    }

    private void receptionMsgDemandeLancementVague(JSONObject json) throws JSONException, CanalException
    {
      // Récupération du type de vague
        int nbCreatures = json.getInt("NB_CREATURES");
        int typeCreature = json.getInt("TYPE_CREATURE");
        // Demande de lancement d'une vague
        int code = serveur.lancerVague(joueur, nbCreatures, typeCreature)
        // Retour au client de l'information
        repondreEtat(VAGUE, code);
    }

    private void receptionMsgDemandeEnvoieMessage(JSONObject json) throws JSONException, CanalException
    {
      log("Message reçu de " + joueur.getId());
    
        // Extraction de la cible du message
        int cible = json.getInt("CIBLE");
        log("Message pour " + cible);
       
        // Extraction du texte du message
        String text = json.getString("MESSAGE");
       
        log("Texte : " + text);
       
        if (cible == A_TOUS) {
            // On broadcast le message à tous les clients
            serveur.envoyerMessageChatPourTous(joueur.getId(), text);
        }
        else {
            // On envoi un message à un client en particulier
            serveur.envoyerMsgClient(joueur.getId(), cible, text);
        }
    }

    /**
   * Répond au client un code d'état pour une réponse donnée
   *
   * @param player
   * @param code
   * @throws JSONException
   * @throws CanalException
   */
  private void repondreEtat(int type, int code)
      throws JSONException, CanalException
  {
    // Message JSON
    JSONObject message = new JSONObject();
   
    // Construction de la structure JSON
    message.put("TYPE", type);
    message.put("STATUS", code);
    // Envoi de la structure à travers le réseau
    envoyer(message.toString());
  }

  /**
   * Termine la liaison avec le client
   * @throws CanalException
   */
  private void fermerCanal() throws CanalException
  {
    canal.fermer();
  }

  /**
   * Donne une représentation sous forme de chaine de caractère de l'état
   * actuel du client
   *
   * @param etat
   *            L'état actuel du client
   * @return Une chaine de caractère
   */
  private static String getNomEtat(int etat)
  {
    switch (etat)
    {
    case EN_ATTENTE:
      return "En attente";
    case EN_JEU:
      return "En jeu";
    case EN_PAUSE:
      return "En pause";
    case VALIDATION:
      return "Validation";
    case PARTIE_TERMINEE:
      return "Partie terminée";
    case QUITTE:
      return "Quitte la partie";
    default:
      return "<BAD>";
    }
  }

  /**
   * Envoi sur le canal de mise à jour le message en paramêtre
   *
   * @param message
   *            Le message à envoyer
   * @throws CanalException
   */
  public synchronized void envoyerSurCanalMAJ(String message)
      throws CanalException
  {
    if(canal_update != null)
        canal_update.envoyerString(message);
    else
        logErreur("Canal_update null",null);
  }
 
  /**
   * Permet d'afficher une message log
   *
   * @param msg le message
   */
  private void log(String msg)
    {
        if(verbeux)
            ServeurJeu.log("[JOUEUR " + joueur.getId() + "]" + msg);
    }
 
    /**
     * Permet d'afficher des message log d'erreur
     *
     * @param msg le message
     */
    private void logErreur(String msg, Exception e)
    {
        System.err.println("[JOUEUR " + joueur.getId() + "]" + msg);
       
        if(e != null)
            e.printStackTrace();
    }

    public int getId()
    {
        return joueur.getId();
    }
}
TOP

Related Classes of reseau.jeu.serveur.JoueurDistant

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.