/** * Teste si un personnage doit etre connecte : il est mort, il triche, ou son temps sur l'arene * est ecoule. Si oui, le deconnecte. * * @param refRMI reference du personnage * @return vrai si le personnage a ete deconnecte, faux sinon * @throws RemoteException */ private boolean verifieDeconnexion(int refRMI) throws RemoteException { boolean res = true; Personnage personnage = (Personnage) elementFromRef(refRMI); if (!personnage.estVivant()) { // on teste si le client est vivant logger.info( Constantes.nomClasse(this), nomRaccourciClient(refRMI) + " est mort... Client ejecte"); deconnecte(refRMI, "Vous etes mort...", "mort naturelle"); } else if (!verifieCaracts(personnage)) { // on teste la triche logger.info( Constantes.nomClasse(this), nomRaccourciClient(refRMI) + " est un tricheur... Client ejecte"); deconnecte(refRMI, "Vous etes mort pour cause de triche...", "SHAME!"); } else if (!personnages.get(refRMI).resteTours()) { // on teste le nombre de tours logger.info( Constantes.nomClasse(this), "Fin du nombre de tours de " + nomRaccourciClient(refRMI) + "... Client ejecte"); deconnecte(refRMI, "Temps autorise dans l'arene ecoule, vous etes elimine !", "temps ecoule"); } else { res = false; } return res; }
@Override public synchronized boolean connecte( int refRMI, String ipConsole, Personnage personnage, int nbTours, Point position) throws RemoteException { // assignation d'un port unique a chaque personnage int portConsole = port + refRMI; String adr = Constantes.nomRMI(ipConsole, portConsole, "Console" + refRMI); boolean res = true; try { logger.info(Constantes.nomClasse(this), "Demande de connexion (" + adr + ")"); // ajout du personnage a la liste personnages.put(refRMI, new VuePersonnage(ipConsole, personnage, nbTours, position, refRMI)); logger.info(Constantes.nomClasse(this), "Connexion acceptee (" + adr + ")"); logElements(); } catch (Exception e) { logger.severe(Constantes.nomClasse(this), "Echec de connexion (" + adr + ")"); e.printStackTrace(); ejectePersonnage(refRMI); res = false; } return res; }
/** * Renvoie la console correspondant a la reference RMI donnee. * * @param refRMI reference RMI * @return console correspondante * @throws RemoteException */ protected IConsole consoleFromRef(int refRMI) throws RemoteException { int p = port + refRMI; String ip = null; String adr = null; IConsole console = null; try { ip = personnages.get(refRMI).getAdresseIp(); adr = Constantes.nomRMI(ip, p, "Console" + refRMI); console = (IConsole) Naming.lookup(adr); } catch (MalformedURLException e) { console = null; logger.severe(Constantes.nomClasse(this), "Erreur : acces a " + adr + "\n" + e.toString()); e.printStackTrace(); } catch (NotBoundException e) { console = null; logger.severe(Constantes.nomClasse(this), "Erreur : acces a " + adr + "\n" + e.toString()); e.printStackTrace(); } catch (NullPointerException e) { console = null; } return console; }
/** * Ajoute l'increment donne a la caracteristique donne de l'element correspondant a la vue donnee. * L'increment peut etre positif ou negatif. * * @param vuePersonnage client a mettre a jour * @param carac caracteristique a mettre a jour * @param increment increment a ajouter a la valeur de la caracteristique courante * @throws RemoteException */ public void incrementeCaractElement( VuePersonnage vuePersonnage, Caracteristique carac, int increment) throws RemoteException { int refRMI = vuePersonnage.getRefRMI(); IConsole console = consoleFromRef(refRMI); Personnage pers = vuePersonnage.getElement(); if (carac == Caracteristique.VIE && increment < 0) { increment = (increment * (100 - pers.getCaract(Caracteristique.ARMURE))) / 100; } // increment de la caracteristique pers.incrementeCaract(carac, increment); if (pers.estVivant()) { if (increment < 0) { console.log( Level.INFO, Constantes.nomClasse(this), "J'ai perdu " + -increment + " points de " + carac); if (carac == Caracteristique.VIE) { setPhrase(refRMI, "Ouch, j'ai perdu " + increment + " points de vie."); } } else { console.log( Level.INFO, Constantes.nomClasse(this), "J'ai gagne " + increment + " points de " + carac); } } }
@Override public synchronized void ajoutePotion(Potion potion, Point position) throws RemoteException { int refRMI = alloueRefRMI(); VuePotion vuePotion = new VuePotion(potion, position, refRMI); // ajout de la potion a la liste potions.put(refRMI, vuePotion); logger.info( Constantes.nomClasse(this), "Ajout de la potion " + Constantes.nomCompletClient(vuePotion) + " (" + refRMI + ")"); logElements(); }
@Override public boolean ramassePotion(int refRMI, int refPotion) throws RemoteException { boolean res = false; VuePersonnage vuePersonnage = personnages.get(refRMI); VuePotion vuePotion = potions.get(refPotion); if (vuePersonnage.isActionExecutee()) { // si une action a deja ete executee logActionDejaExecutee(refRMI); } else { // sinon, on tente de jouer l'interaction int distance = Calculs.distanceChebyshev(vuePersonnage.getPosition(), vuePotion.getPosition()); // on teste la distance entre le personnage et la potion if (distance <= Constantes.DISTANCE_MIN_INTERACTION) { new Ramassage(this, vuePersonnage, vuePotion).interagit(); personnages.get(refRMI).executeAction(); res = true; } else { logger.warning( Constantes.nomClasse(this), nomRaccourciClient(refRMI) + " a tente d'interagir avec " + vuePotion.getElement().getNom() + ", alors qu'il est trop eloigne !\nDistance = " + distance); } } return res; }
/** * Retourne une chaine de caracteres avec les noms complets de tous les clients connectes (et * personnages ayant ete deconnectes). * * @return chaine representant les clients du serveur */ protected String getPrintElementsMessage() { String msg = ""; for (VuePersonnage vuePers : personnages.values()) { msg += "\n" + Constantes.nomCompletClient(vuePers); } for (VuePersonnage vuePers : personnagesMorts) { msg += "\n" + Constantes.nomCompletClient(vuePers); } for (VuePotion vuePot : potions.values()) { msg += "\n" + Constantes.nomCompletClient(vuePot); } return msg; }
/** * Ajoute les logs dans le cas ou le personnage correspondant a la console donnee a tenter * d'executer plusieurs fois une action dans le meme tour. * * @param refRMI console * @throws RemoteException */ private void logActionDejaExecutee(int refRMI) throws RemoteException { consoleFromRef(refRMI) .log(Level.WARNING, "AVERTISSEMENT ARENE", "Une action a deja ete executee ce tour-ci !"); logger.warning( Constantes.nomClasse(this), nomRaccourciClient(refRMI) + " a tente de jouer plusieurs actions dans le meme tour"); }
@Override public boolean regenerationMana(int refRMI, int mana) throws RemoteException { VuePersonnage pCible = personnages.get(refRMI); IConsole console = consoleFromRef(refRMI); console.log(Level.INFO, Constantes.nomClasse(this), "Je regagne " + mana + " Mana "); new RegenerationMana(this, pCible).regenMana(mana); return true; }
@Override public boolean ajouteArmure(int refRMI, int armure) throws RemoteException { VuePersonnage pCible = personnages.get(refRMI); IConsole console = consoleFromRef(refRMI); console.log(Level.INFO, Constantes.nomClasse(this), "Je gagne " + armure + " armure "); this.incrementeCaractElement(pCible, Caracteristique.ARMURE, armure); return true; }
@Override public boolean soin(int refRMI, int mana, int pv) throws RemoteException { // TODO Auto-generated method stub VuePersonnage pASoigner = personnages.get(refRMI); IConsole console = consoleFromRef(refRMI); console.log( Level.INFO, Constantes.nomClasse(this), "Je me soigne de " + pv + " contre " + mana); new Soin(this, pASoigner).soigner(mana, pv); return true; }
/** Affiche le classement de la partie dans le logger. */ private void logClassement() { List<VuePersonnage> classement = getPersonnagesClassement(); String msg = ""; int i = 1; for (VuePersonnage vue : classement) { msg += "\n" + i + " : " + vue.getElement().getNomGroupe() + " " + vue.getPhrase(); i++; } logger.info(Constantes.nomClasse(this), "Classement :" + msg); }
@Override public void interagit() { try { Personnage pAttaquant = attaquant.getElement(); // init int forceAttaquant = pAttaquant.getCaract(Caracteristique.FORCE); Personnage pDefenseur = defenseur.getElement(); int defenseDefenseur = pDefenseur.getCaract(Caracteristique.DEFENSE); // on prend en compte la Defense int perteVie = forceAttaquant * (100 - defenseDefenseur) / 100; Point positionEjection = positionEjection(defenseur.getPosition(), attaquant.getPosition(), forceAttaquant); // ejection du defenseur defenseur.setPosition(positionEjection); // degats if (perteVie > 0) { arene.incrementeCaractElement(defenseur, Caracteristique.VIE, -perteVie); logs( Level.INFO, Constantes.nomRaccourciClient(attaquant) + " colle une beigne paralysante (" + perteVie + " points de degats) a " + Constantes.nomRaccourciClient(defenseur)); } // paralysie paralysie(defenseur); // initiative incrementeInitiative(defenseur); decrementeInitiative(attaquant); } catch (RemoteException e) { logs(Level.INFO, "\nErreur lors d'une attaque : " + e.toString()); } }
/** Ferme le serveur a la fin de la partie. */ private void fermerServeur() { // afficher le classement dans le log logClassement(); // a la fin de la partie, on ferme la "porte" RMI try { // deconnection des clients List<Integer> listRef = getSortedRefs(); for (int refRMI : listRef) { deconnecte(refRMI, "Fermeture du serveur", ""); } logger.info(Constantes.nomClasse(this), "Fin de la partie ! Fermeture du serveur"); unexportObject(this, true); logger.info(Constantes.nomClasse(this), "Serveur ferme"); } catch (RemoteException e) { e.printStackTrace(); System.exit(1); } }
/** * Constructeur de l'arene. * * @param port le port de connexion * @param adresseIP nom de la machine qui heberge l'arene * @param nbTours duree de vue du serveur en nombre de tours de jeu (si negatif, duree illimitee) * @param logger gestionnaire de log * @throws RemoteException * @throws MalformedURLException */ public Arene(int port, String adresseIP, int nbTours, LoggerProjet logger) throws RemoteException, MalformedURLException { super(); this.port = port; this.adresseIP = adresseIP; this.NB_TOURS = nbTours; personnages = new Hashtable<Integer, VuePersonnage>(); potions = new Hashtable<Integer, VuePotion>(); personnagesMorts = new ArrayList<VuePersonnage>(); this.logger = logger; // ajout de l'arene au registre RMI Naming.rebind(adrToString(), this); logger.info(Constantes.nomClasse(this), "Arene cree a l'adresse " + adrToString()); new Thread(this).start(); }
public void lancerPotionTeleportation(int port, String ipArene) { String nom = "Téléportation"; // TODO remplacer la ligne suivante par votre numero de groupe String groupe = "G7"; // creation du logger LoggerProjet logger = null; try { logger = new LoggerProjet(true, "potion_" + nom + groupe); } catch (IOException e) { e.printStackTrace(); System.exit(ErreurLancement.suivant); } // lancement de la potion try { IArene arene = (IArene) java.rmi.Naming.lookup(Constantes.nomRMI(ipArene, port, "Arene")); logger.info("Lanceur", "Lancement de la potion sur le serveur..."); // caracteristiques de la potion HashMap<Caracteristique, Integer> caracts = new HashMap<Caracteristique, Integer>(); caracts.put(Caracteristique.VIE, 0); caracts.put(Caracteristique.FORCE, 0); caracts.put(Caracteristique.INITIATIVE, 0); caracts.put(Caracteristique.ESQUIVE, 0); caracts.put(Caracteristique.DEFENSE, 0); caracts.put(Caracteristique.BOUCLIER, 0); // ajout de la potion arene.ajoutePotion(new Potion(nom, groupe, caracts), Calculs.positionAleatoireArene()); logger.info("Lanceur", "Lancement de la potion reussi"); } catch (Exception e) { logger.severe("Lanceur", "Erreur lancement :\n" + e.getCause()); e.printStackTrace(); System.exit(ErreurLancement.suivant); } }
/** * Ejecte un personnage : le retire de la liste des vivants et ajoute une information dans le log. * * @param refRMI reference du personnage a ejecter */ protected void ejectePersonnage(int refRMI) { if (personnages.remove(refRMI) != null) { logger.info(Constantes.nomClasse(this), "Console " + refRMI + " ejectee du registre !"); } }
/** * Construit l'adresse complete de l'arene sous forme de chaine de caracteres. * * @return adresse complete de l'arene */ private String adrToString() { return Constantes.nomRMI(adresseIP, port, "Arene"); }
/** * Retourne le nom raccourci du client correspondant a la reference RMI donnee. * * @param refRMI reference RMI * @return nom raccourci du client */ public String nomRaccourciClient(int refRMI) throws RemoteException { return Constantes.nomRaccourciClient(vueFromRef(refRMI)); }
// TODO : modification de l'interaction avec les differents type de potions @Override public void interagit() { try { logs( Level.INFO, Constantes.nomRaccourciClient(attaquant) + " essaye de rammasser " + Constantes.nomRaccourciClient(defenseur)); // si le personnage est vivant if (attaquant.getElement().estVivant()) { // caracteristiques de la potion HashMap<Caracteristique, Integer> valeursPotion = defenseur.getElement().getCaracts(); int typePotion = valeursPotion.get(Caracteristique.TYPE); if (typePotion == 1) { for (Caracteristique c : valeursPotion.keySet()) { if (c != Caracteristique.TYPE) { arene.incrementeCaractElement( attaquant, c, (int) ((valeursPotion.get(c) / (float) 100) * attaquant.getElement().getCaracts().get(c))); System.out.println(attaquant.getElement().getCaracts().get(c)); System.out.println(valeursPotion.get(c)); } } } else { for (Caracteristique c : valeursPotion.keySet()) { if (c != Caracteristique.TYPE) { arene.incrementeCaractElement(attaquant, c, valeursPotion.get(c)); } } } logs(Level.INFO, "Potion bue !"); // test si mort if (!attaquant.getElement().estVivant()) { arene.setPhrase(attaquant.getRefRMI(), "Je me suis empoisonne, je meurs "); logs( Level.INFO, Constantes.nomRaccourciClient(attaquant) + " vient de boire un poison... Mort >_<"); } // suppression de la potion arene.ejectePotion(defenseur.getRefRMI()); } else { logs( Level.INFO, Constantes.nomRaccourciClient(attaquant) + " ou " + Constantes.nomRaccourciClient(defenseur) + " est deja mort... Rien ne se passe"); } } catch (RemoteException e) { logs(Level.INFO, "\nErreur lors d'un ramassage : " + e.toString()); } }
/** Affiche tous les elements present dans l'arene dans le logger. */ public void logElements() { String msg = getPrintElementsMessage(); logger.info(Constantes.nomClasse(this), "Compte-rendu :" + msg); }
@Override public void run() { // thread executant la strategie de chaque personnage ThreadStrategie ts; // liste qui va contenir les references RMI des personnages, // ordonnees par leur initiative List<Integer> listRef; while (!partieFinie) { // moment de debut du tour long begin = System.currentTimeMillis(); // on verouille le serveur durant un tour de jeu pour ne pas avoir // de connexion/deconnexion synchronized (this) { // tri des references par initiative listRef = getSortedRefs(); // pour chaque personnage, on joue sa strategie for (int refRMI : listRef) { try { // si pas deconnecte if (!verifieDeconnexion(refRMI)) { // lancement de la strategie (dans un thread separe) ts = new ThreadStrategie(consoleFromRef(refRMI)); // attente de la fin de la strategie (temps d'attente max 1 seconde) ts.join(1000); // finit le tour pour ce client personnages.get(refRMI).termineTour(); if (ts.isAlive()) { // si le thread est toujours vivant apres une // seconde (la strategie n'est pas terminee), // on l'ejecte logger.info( Constantes.nomClasse(this), "Execution de la strategie de " + nomRaccourciClient(refRMI) + " trop longue ! Client ejecte"); deconnecte(refRMI, "Execution de strategie trop longue. Degage !", "trop lent"); } else { // on reteste apres l'execution de la strategie verifieDeconnexion(refRMI); } } } catch (RemoteException e) { logger.severe( Constantes.nomClasse(this), "Erreur dans le run " + "avec la console de reference " + refRMI + "\n" + e.toString()); e.printStackTrace(); ejectePersonnage(refRMI); } catch (InterruptedException e) { e.printStackTrace(); } } } tour++; verifierPartieFinie(); try { long dureeTour = System.currentTimeMillis() - begin; // dormir au plus 1 seconde pour permettre // la connexion/deconnexion des consoles long time = 1000 - dureeTour; if (time > 0) { Thread.sleep(time); } } catch (InterruptedException e) { logger.severe(Constantes.nomClasse(this), "Erreur : run\n" + e.toString()); e.printStackTrace(); } } fermerServeur(); }
public boolean Vampirise(int refRMI, int refRMIAdv) throws RemoteException { boolean res = false; VuePersonnage client = personnages.get(refRMI); VuePersonnage clientAdv = personnages.get(refRMIAdv); if (personnages.get(refRMI).isActionExecutee()) { // si une action a deja ete executee logActionDejaExecutee(refRMI); } else { // sinon, on tente de jouer l'interaction IConsole console = consoleFromRef(refRMI); IConsole consoleAdv = consoleFromRef(refRMIAdv); int distance = Calculs.distanceChebyshev( personnages.get(refRMI).getPosition(), personnages.get(refRMIAdv).getPosition()); // on teste la distance entre les personnages if (distance <= Constantes.DISTANCE_MIN_INTERACTION) { Personnage pers = (Personnage) elementFromRef(refRMI); Personnage persAdv = (Personnage) elementFromRef(refRMIAdv); // on teste que les deux personnages soient en vie if (pers.estVivant() && persAdv.estVivant()) { console.log( Level.INFO, Constantes.nomClasse(this), "Je decoupe " + nomRaccourciClient(refRMIAdv)); consoleAdv.log( Level.INFO, Constantes.nomClasse(this), "Je me fait massacrer par " + nomRaccourciClient(refRMI)); logger.info( Constantes.nomClasse(this), nomRaccourciClient(refRMI) + " attaque " + nomRaccourciClient(consoleAdv.getRefRMI())); new Vampirise(this, client, clientAdv).interagit(); personnages.get(refRMI).executeAction(); // si l'adversaire est mort if (!persAdv.estVivant()) { setPhrase(refRMI, "Je tue " + nomRaccourciClient(consoleAdv.getRefRMI())); console.log( Level.INFO, Constantes.nomClasse(this), "Je tue " + nomRaccourciClient(refRMI)); logger.info( Constantes.nomClasse(this), nomRaccourciClient(refRMI) + " tue " + nomRaccourciClient(consoleAdv.getRefRMI())); } res = true; } else { logger.warning( Constantes.nomClasse(this), nomRaccourciClient(refRMI) + " a tente d'interagir avec " + nomRaccourciClient(refRMIAdv) + ", alors qu'il est mort..."); console.log( Level.WARNING, Constantes.nomClasse(this), nomRaccourciClient(refRMIAdv) + " est deja mort !"); } } else { logger.warning( Constantes.nomClasse(this), nomRaccourciClient(refRMI) + " a tente d'interagir avec " + nomRaccourciClient(refRMIAdv) + ", alors qu'il est trop eloigne... Distance de chebyshev = " + distance); console.log( Level.WARNING, "AVERTISSEMENT ARENE", nomRaccourciClient(refRMIAdv) + " est trop eloigne !\nDistance = " + distance); } } return res; }
@Override public void interagit() { Potion Potion = defenseur.getElement(); try { logs( Level.INFO, Constantes.nomRaccourciClient(attaquant) + " essaye de rammasser " + Constantes.nomRaccourciClient(defenseur)); // si le personnage est vivant if (attaquant.getElement().estVivant()) { // caracteristiques de la potion HashMap<Caracteristique, Integer> valeursPotion = defenseur.getElement().getCaracts(); if (Potion.getNom().equals("teleportation")) { arene.setPhrase(attaquant.getRefRMI(), "Je me teleporte"); Point p; p = attaquant.getPosition(); p.x = (int) (Math.random() * (Constantes.XMAX_ARENE - Constantes.XMIN_ARENE)) + Constantes.XMIN_ARENE; p.y = (int) (Math.random() * (Constantes.YMAX_ARENE - Constantes.YMIN_ARENE)) + Constantes.YMIN_ARENE; arene.deplace(attaquant.getRefRMI(), p); } else if (Potion.getNom().equals("immobilite")) { arene.setPhrase(attaquant.getRefRMI(), "Je deviens immobile pour 5 tours"); this.attaquant.getElement().nbToursImm = 5; System.err.println("nb tour: " + this.attaquant.getElement().nbToursImm); } else { for (Caracteristique c : valeursPotion.keySet()) { arene.incrementeCaractElement(attaquant, c, valeursPotion.get(c)); } logs(Level.INFO, "Potion bue !"); // test si mort if (!attaquant.getElement().estVivant()) { arene.setPhrase(attaquant.getRefRMI(), "Je me suis empoisonne, je meurs "); logs( Level.INFO, Constantes.nomRaccourciClient(attaquant) + " vient de boire un poison... Mort >_<"); } } if (!Potion.getNom().equals("nitro")) { attaquant.getElement().getCaracts().put(Caracteristique.VITESSE, 1); } // suppression de la potion arene.ejectePotion(defenseur.getRefRMI()); } else { logs( Level.INFO, Constantes.nomRaccourciClient(attaquant) + " ou " + Constantes.nomRaccourciClient(defenseur) + " est deja mort... Rien ne se passe"); } } catch (RemoteException e) { logs(Level.INFO, "\nErreur lors d'un ramassage : " + e.toString()); } }