From ace2c2c94839bb730d13707cfca5054445fb83da Mon Sep 17 00:00:00 2001 From: Coutume Date: Wed, 12 Mar 2014 19:08:51 +0100 Subject: [PATCH] update source --- src/fr/moribus/ImageOnMap/ImageOnMap.java | 8 +- .../ImageOnMap/ImageRendererThread.java | 37 ++-- .../ImageOnMap/ImageRenduCommande.java | 13 +- src/fr/moribus/ImageOnMap/ImgUtility.java | 4 +- src/fr/moribus/ImageOnMap/MapToolCommand.java | 27 ++- src/fr/moribus/ImageOnMap/PlayerListener.java | 43 +++++ src/fr/moribus/ImageOnMap/SavedMap.java | 9 +- src/fr/moribus/ImageOnMap/SavedPoster.java | 165 ++++++++++++++++++ .../moribus/ImageOnMap/SendEntireMapTask.java | 81 +++++++++ .../ImageOnMap/SendMapOnFrameEvent.java | 8 +- .../moribus/ImageOnMap/SendMapOnInvEvent.java | 2 - .../ImageOnMap/TacheTraitementMap.java | 44 ++++- 12 files changed, 404 insertions(+), 37 deletions(-) create mode 100644 src/fr/moribus/ImageOnMap/PlayerListener.java create mode 100644 src/fr/moribus/ImageOnMap/SavedPoster.java create mode 100644 src/fr/moribus/ImageOnMap/SendEntireMapTask.java diff --git a/src/fr/moribus/ImageOnMap/ImageOnMap.java b/src/fr/moribus/ImageOnMap/ImageOnMap.java index e6dd0fa..12d9e80 100644 --- a/src/fr/moribus/ImageOnMap/ImageOnMap.java +++ b/src/fr/moribus/ImageOnMap/ImageOnMap.java @@ -17,7 +17,7 @@ public final class ImageOnMap extends JavaPlugin { int test = 0; File dossier; - boolean dossierCree; + private boolean dossierCree; private FileConfiguration customConfig = null; private File customConfigFile = null; /* liste contenant les maps ne pouvant être placé dans l'inventaire du joueur. Je le fous ici afin que ce soit @@ -62,6 +62,7 @@ public final class ImageOnMap extends JavaPlugin if(getConfig().getBoolean("import-maps")) ImgUtility.ImporterConfig(this); + ChargerMap(); if(this.getConfig().getBoolean("collect-data")) { try @@ -69,7 +70,8 @@ public final class ImageOnMap extends JavaPlugin MetricsLite metrics = new MetricsLite(this); metrics.start(); getLogger().info("Metrics launched for ImageOnMap"); - } catch (IOException e) { + } catch (IOException e) + { // Failed to submit the stats :-( } } @@ -80,6 +82,7 @@ public final class ImageOnMap extends JavaPlugin getCommand("maptool").setExecutor(new MapToolCommand(this)); getServer().getPluginManager().registerEvents(new SendMapOnFrameEvent(this), this); getServer().getPluginManager().registerEvents(new SendMapOnInvEvent(this), this); + getServer().getPluginManager().registerEvents(new PlayerListener(this), this); this.saveDefaultConfig(); //ChargerMap(); } @@ -175,5 +178,4 @@ public final class ImageOnMap extends JavaPlugin { cache.remove(j); } - } diff --git a/src/fr/moribus/ImageOnMap/ImageRendererThread.java b/src/fr/moribus/ImageOnMap/ImageRendererThread.java index 999db94..d637808 100644 --- a/src/fr/moribus/ImageOnMap/ImageRendererThread.java +++ b/src/fr/moribus/ImageOnMap/ImageRendererThread.java @@ -4,6 +4,7 @@ import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URI; import java.util.HashMap; @@ -19,7 +20,7 @@ public class ImageRendererThread extends Thread private BufferedImage[] img; private Poster poster; private boolean estPrete = false, resized; - boolean erreur = false; + public boolean erreur = false; public boolean isErreur() { @@ -54,12 +55,34 @@ public class ImageRendererThread extends Thread } @Override - public void run() + public void run() { + URI uri = null; + java.net.URL url = null; try { - imgSrc = ImageIO.read(URI.create(URL).toURL().openStream()); + uri = URI.create(URL); + url = uri.toURL(); + + } + catch (IllegalArgumentException | MalformedURLException e) { + e.printStackTrace(); + + erreur = true; + return; + } + if(erreur != true) + { + try { + imgSrc = ImageIO.read(url.openStream()); + + + } catch (IOException e) { + // TODO Auto-generated catch block + erreur = true; + e.printStackTrace(); + } if(resized) { img = new BufferedImage[1]; @@ -113,14 +136,8 @@ public class ImageRendererThread extends Thread img = poster.getPoster(); } - + estPrete = true; } - catch (IOException e) { - e.printStackTrace(); - erreur = true; - } - - estPrete = true; } diff --git a/src/fr/moribus/ImageOnMap/ImageRenduCommande.java b/src/fr/moribus/ImageOnMap/ImageRenduCommande.java index eeb82c6..15f17f2 100644 --- a/src/fr/moribus/ImageOnMap/ImageRenduCommande.java +++ b/src/fr/moribus/ImageOnMap/ImageRenduCommande.java @@ -44,9 +44,20 @@ public class ImageRenduCommande implements CommandExecutor if (arg3.length < 1) { - joueur.sendMessage(ChatColor.RED + "You must enter image url"); + joueur.sendMessage(ChatColor.RED + "You must enter image url."); return false; } + if(!arg3[0].startsWith("http")) + { + joueur.sendMessage("You must enter a valid URL."); + return true; + } + else if(arg3[0].startsWith("https")) + { + joueur.sendMessage("WARNING: you have entered a secure HTTP link, ImageOnMap can't guarantee " + + "that the image is downloadable"); + return true; + } /*if(arg3.length == 1 && arg3[0].equalsIgnoreCase("test")) { diff --git a/src/fr/moribus/ImageOnMap/ImgUtility.java b/src/fr/moribus/ImageOnMap/ImgUtility.java index 672433f..15f5998 100644 --- a/src/fr/moribus/ImageOnMap/ImgUtility.java +++ b/src/fr/moribus/ImageOnMap/ImgUtility.java @@ -56,6 +56,8 @@ public class ImgUtility plugin.getConfig().set("collect-data", true); if(plugin.getConfig().get("import-maps") == null) plugin.getConfig().set("import-maps", true); + if(plugin.getConfig().get("send-entire-maps") == null) + plugin.getConfig().set("send-entire-maps", 0); plugin.saveConfig(); } @@ -220,7 +222,7 @@ public class ImgUtility } } - plugin.getLogger().info("No map with id"+ id+ " was found"); + //plugin.getLogger().info("No map with id"+ id+ " was found"); return false; } diff --git a/src/fr/moribus/ImageOnMap/MapToolCommand.java b/src/fr/moribus/ImageOnMap/MapToolCommand.java index abd9291..8e41016 100644 --- a/src/fr/moribus/ImageOnMap/MapToolCommand.java +++ b/src/fr/moribus/ImageOnMap/MapToolCommand.java @@ -2,6 +2,7 @@ package fr.moribus.ImageOnMap; import java.util.ArrayList; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.command.Command; @@ -58,9 +59,10 @@ public class MapToolCommand implements CommandExecutor return true; } - map = ImgUtility.getMap(plugin, id); + SavedMap smap = new SavedMap(plugin, id); + //map = ImgUtility.getMap(plugin, id); - if(map == null) + if(!smap.LoadMap()) { if(joueur.isOp()) joueur.sendMessage(ChatColor.RED+ "Can't retrieve the map ! Check if map"+ id+ " exists in your maps.yml or if the dat file in the world folder exists"); @@ -76,6 +78,7 @@ public class MapToolCommand implements CommandExecutor return true; } + map = Bukkit.getMap(id); inv.addItem(new ItemStack(Material.MAP, 1, map.getId())); joueur.sendMap(map); joueur.sendMessage("Map "+ ChatColor.ITALIC+ id+ ChatColor.RESET+ " was added in your inventory."); @@ -91,6 +94,15 @@ public class MapToolCommand implements CommandExecutor return true; } + if(arg3.length == 2 && arg3[1].startsWith("poster")) + { + SavedPoster poster = new SavedPoster(plugin, arg3[1]); + boolean suppr = poster.Remove(); + if(!suppr) + joueur.sendMessage("Unable to remove the entire poster, check the server log for more information"); + return true; + } + if(arg3.length <= 1) { if(joueur.getItemInHand().getType() == Material.MAP) @@ -131,7 +143,7 @@ public class MapToolCommand implements CommandExecutor else if(arg3[0].equalsIgnoreCase("list")) { - String msg = ""; + String msg = "", msg2 = ""; int compteur = 0; ArrayList liste = new ArrayList(); @@ -141,8 +153,17 @@ public class MapToolCommand implements CommandExecutor { msg += liste.get(compteur)+ " "; } + + SavedPoster tmp = new SavedPoster(plugin); + ArrayList listePoster = tmp.getListMapByPlayer(plugin, joueur.getName()); + for (int i= 0; i< listePoster.size(); i++) + { + msg2 += listePoster.get(i)+ " "; + } joueur.sendMessage(msg+ "\nYou have rendered "+ ChatColor.DARK_PURPLE+ (compteur + 1)+ ChatColor.RESET+ " pictures"); + joueur.sendMessage("Your posters: \n"+ msg2); + } else if(arg3[0].equalsIgnoreCase("getrest")) diff --git a/src/fr/moribus/ImageOnMap/PlayerListener.java b/src/fr/moribus/ImageOnMap/PlayerListener.java new file mode 100644 index 0000000..23f6d10 --- /dev/null +++ b/src/fr/moribus/ImageOnMap/PlayerListener.java @@ -0,0 +1,43 @@ +package fr.moribus.ImageOnMap; + +import java.util.HashMap; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class PlayerListener implements Listener +{ + ImageOnMap plugin; + HashMap hmap; + int send; + + PlayerListener(ImageOnMap p) + { + plugin = p; + hmap = new HashMap(); + send = plugin.getConfig().getInt("send-entire-maps"); + } + @EventHandler + public void OnPlayerLogin(PlayerLoginEvent event) + { + if(send > 0) + { + Player joueur = event.getPlayer(); + hmap.put(joueur.getName(), new SendEntireMapTask(plugin, event.getPlayer())); + hmap.get(joueur.getName()).runTaskTimer(plugin, 40, 20); + } + } + + @EventHandler + public void OnPlayerLeft(PlayerQuitEvent event) + { + if(send > 0) + { + Player joueur = event.getPlayer(); + hmap.get(joueur.getName()).cancel(); + } + } +} diff --git a/src/fr/moribus/ImageOnMap/SavedMap.java b/src/fr/moribus/ImageOnMap/SavedMap.java index 5a10f62..e9fa551 100644 --- a/src/fr/moribus/ImageOnMap/SavedMap.java +++ b/src/fr/moribus/ImageOnMap/SavedMap.java @@ -56,12 +56,17 @@ public class SavedMap } if(!loaded) { - plugin.getLogger().info("No map was loaded"); + //plugin.getLogger().info("No map was loaded"); } } Boolean SaveMap() { + if(!loaded) + { + plugin.getLogger().info("Cannot save the map !"); + return false; + } plugin.getLogger().info("Saving map " + idMap); // Enregistrement de l'image sur le disque dur @@ -82,6 +87,8 @@ public class SavedMap liste.add(nomMonde); plugin.getCustomConfig().set(nomImg, liste); plugin.saveCustomConfig(); + if(!plugin.mapChargee.contains(idMap)) + plugin.mapChargee.add(idMap); return true; } diff --git a/src/fr/moribus/ImageOnMap/SavedPoster.java b/src/fr/moribus/ImageOnMap/SavedPoster.java new file mode 100644 index 0000000..f5f89c1 --- /dev/null +++ b/src/fr/moribus/ImageOnMap/SavedPoster.java @@ -0,0 +1,165 @@ +package fr.moribus.ImageOnMap; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Set; +import java.util.logging.Level; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +public class SavedPoster +{ + ImageOnMap plugin; + short[] ids; + private FileConfiguration customConfig = null; + private File customConfigFile = null; + String PosName, nomJoueur; + + SavedPoster(ImageOnMap p, short[] i, String nom) + { + ids = i; + plugin = p; + nomJoueur = nom; + PosName = ""; + } + + SavedPoster(ImageOnMap p, short[] i, String nom, String n) + { + ids = i; + plugin = p; + nomJoueur = nom; + PosName = n; + + } + + SavedPoster(ImageOnMap p, String id) + { + plugin = p; + PosName = id; + ArrayList liste = (ArrayList) getCustomConfig().getStringList(PosName); + if(!liste.isEmpty() || liste != null) + { + nomJoueur = liste.get(0); + ids = new short[liste.size() - 1]; + for(int i= 0; i< ids.length; i++) + { + ids[i] = Short.parseShort(liste.get(i+1)); + } + } + } + + SavedPoster(ImageOnMap p) + { + plugin = p; + } + + + String Save() + { + int increment = increment(); + ArrayList liste = new ArrayList(); + liste.add(nomJoueur); + for(int i= 0; i< ids.length; i++) + { + liste.add(String.valueOf(ids[i])); + } + PosName = "poster"+ increment; + getCustomConfig().set(PosName, liste); + saveCustomConfig(); + return PosName; + } + + boolean Remove() + { + if(!PosName.isEmpty()) + { + for(int i= 0; i< ids.length; i++) + { + ImgUtility.RemoveMap(plugin, ids[i]); + } + getCustomConfig().set(PosName, null); + saveCustomConfig(); + return true; + } + else + return false; + + } + + int increment() + { + int i; + if(getCustomConfig().get("IdCount") != null) + i = getCustomConfig().getInt("IdCount"); + else + i = 0; + i++; + this.getCustomConfig().set("IdCount", i); + return i; + } + + String getId() + { + return PosName; + } + + ArrayList getListMapByPlayer(ImageOnMap plugin, String pseudo) + { + ArrayList listeMap = new ArrayList(); + Set cle = getCustomConfig().getKeys(false); + for (String s: cle) + { + if(getCustomConfig().getStringList(s).size() > 1 && pseudo.equalsIgnoreCase(getCustomConfig().getStringList(s).get(0))) + { + listeMap.add(s); + } + } + return listeMap; + } + + /* Méthodes pour charger / recharger / sauvegarder + * le fichier conf des Posters (poster.yml). + * Je les ai juste copié depuis un tuto du wiki Bukkit... + */ + public void reloadCustomConfig() + { + if (customConfigFile == null) + { + customConfigFile = new File(plugin.getDataFolder(), "poster.yml"); + } + customConfig = YamlConfiguration.loadConfiguration(customConfigFile); + + // Look for defaults in the jar + InputStream defConfigStream = plugin.getResource("poster.yml"); + if (defConfigStream != null) + { + YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream); + customConfig.setDefaults(defConfig); + } + } + + public FileConfiguration getCustomConfig() + { + if (customConfig == null) + { + reloadCustomConfig(); + } + return customConfig; + } + + public void saveCustomConfig() + { + if (customConfig == null || customConfigFile == null) { + return; + } + try { + getCustomConfig().save(customConfigFile); + } catch (IOException ex) { + plugin.getLogger().log(Level.SEVERE, "Could not save config to " + customConfigFile, ex); + } + } + +} diff --git a/src/fr/moribus/ImageOnMap/SendEntireMapTask.java b/src/fr/moribus/ImageOnMap/SendEntireMapTask.java new file mode 100644 index 0000000..61999dd --- /dev/null +++ b/src/fr/moribus/ImageOnMap/SendEntireMapTask.java @@ -0,0 +1,81 @@ +package fr.moribus.ImageOnMap; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.map.MapView; +import org.bukkit.scheduler.BukkitRunnable; + +public class SendEntireMapTask extends BukkitRunnable +{ + ImageOnMap plugin; + Player joueur; + ArrayList listeMap; + List partListe; + boolean allsent; + int index, toIndex, nbSend; + + SendEntireMapTask(ImageOnMap p, Player j) + { + plugin = p; + joueur = j; + allsent = false; + index = 0; + nbSend = plugin.getConfig().getInt("send-entire-maps"); + toIndex = nbSend; + } + + @SuppressWarnings("deprecation") + @Override + public void run() + { + if(nbSend > 0) + { + if(listeMap == null) + { + //plugin.getLogger().info("test de nullité"); + listeMap = new ArrayList(); + listeMap.addAll(plugin.mapChargee); + } + else if(listeMap.equals(plugin.mapChargee) != true) + { + //plugin.getLogger().info("taille des maps : " + listeMap.size()+ " ; "+ plugin.mapChargee.size()); + //plugin.getLogger().info("test d'égalité"); + listeMap.clear(); + listeMap.addAll(plugin.mapChargee); + allsent = false; + } + if(!allsent) + { + //plugin.getLogger().info("test 1"); + if(toIndex > listeMap.size()) + { + //plugin.getLogger().info("test 3"); + partListe = listeMap.subList(index, listeMap.size()); + index = listeMap.size(); + toIndex = listeMap.size() + nbSend; + allsent = true; + } + else + { + //plugin.getLogger().info("taille des index : " + index+ " ; "+ toIndex+ ". taille de la map : " + // + listeMap.size()); + //plugin.getLogger().info("test 2"); + partListe = listeMap.subList(index, toIndex); + index = toIndex; + toIndex += nbSend; + } + for(int i= 0; i< partListe.size(); i++) + { + //plugin.getLogger().info("test 4"); + MapView map = Bukkit.getMap(partListe.get(i)); + joueur.sendMap(map); + } + } + } + + } + +} diff --git a/src/fr/moribus/ImageOnMap/SendMapOnFrameEvent.java b/src/fr/moribus/ImageOnMap/SendMapOnFrameEvent.java index fe8417c..7d41f4d 100644 --- a/src/fr/moribus/ImageOnMap/SendMapOnFrameEvent.java +++ b/src/fr/moribus/ImageOnMap/SendMapOnFrameEvent.java @@ -1,7 +1,6 @@ package fr.moribus.ImageOnMap; import java.util.ArrayList; -import java.util.Set; import org.bukkit.Chunk; import org.bukkit.Material; @@ -22,29 +21,24 @@ public class SendMapOnFrameEvent implements Listener SendMapOnFrameEvent(ImageOnMap plug) { plugin = plug; - plugin.getLogger().info("Loading event"); } + @EventHandler public void onChunkLoad(ChunkLoadEvent event) { chunk = event.getChunk(); - //plugin.getLogger().info("Loading entities.."); entites = chunk.getEntities().clone(); for(int i = 0; i < entites.length; i++) { Entity entite = entites[i]; - //plugin.getLogger().info("entrée dans la boucle"); if(entite instanceof ItemFrame) { ArrayList ListeId = plugin.mapChargee; - //plugin.getLogger().info("entrée dans la condition"); frame = (ItemFrame) entite; ItemStack stack = frame.getItem(); if(stack.getType() == Material.MAP && !ListeId.contains(stack.getDurability())) { - /* c'est dans la méthode LoadMap() qu'on vérifie si la map est bien - une map custom et non une map normale*/ SavedMap map = new SavedMap(plugin, stack.getDurability()); map.LoadMap(); diff --git a/src/fr/moribus/ImageOnMap/SendMapOnInvEvent.java b/src/fr/moribus/ImageOnMap/SendMapOnInvEvent.java index b38add9..fe08cc8 100644 --- a/src/fr/moribus/ImageOnMap/SendMapOnInvEvent.java +++ b/src/fr/moribus/ImageOnMap/SendMapOnInvEvent.java @@ -40,7 +40,6 @@ public class SendMapOnInvEvent implements Listener if(!listeId.contains(stack.getDurability())) { - //plugin.getLogger().info("map"+ stack.getDurability()+ " dans la main du joueur en cours de recherche..."); if(plugin.getCustomConfig().getStringList(s).get(0).equals(String.valueOf(stack.getDurability()))) { SavedMap map = new SavedMap(plugin, Short.valueOf(plugin.getCustomConfig().getStringList(s).get(0))); @@ -49,7 +48,6 @@ public class SendMapOnInvEvent implements Listener plugin.getLogger().log(Level.WARNING, "Unable to load map " +stack.getDurability()); else { - //plugin.getLogger().info("map"+ stack.getDurability()+ " chargée"); break; } diff --git a/src/fr/moribus/ImageOnMap/TacheTraitementMap.java b/src/fr/moribus/ImageOnMap/TacheTraitementMap.java index 23b29c4..d1e0e53 100644 --- a/src/fr/moribus/ImageOnMap/TacheTraitementMap.java +++ b/src/fr/moribus/ImageOnMap/TacheTraitementMap.java @@ -42,7 +42,12 @@ public class TacheTraitementMap extends BukkitRunnable { //joueur.sendMessage("Nombre d'exécution depuis le lancement du timer : " + i); i++; - if(renduImg.isErreur() || i > 42) + if(renduImg.erreur) + { + joueur.sendMessage("There was a problem while fetching image. Check your URL."); + cancel(); + } + if(i > 42) { joueur.sendMessage("TIMEOUT: the render took too many time"); cancel(); @@ -57,14 +62,22 @@ public class TacheTraitementMap extends BukkitRunnable joueur.sendMessage("ERROR: cannot render "+ nbImage +" picture(s): the limit of maps per server would be exceeded."); return; } - if (plugin.getConfig().getInt("Limit-map-by-player") != 0 && nbImage + ImgUtility.getNombreDeMapsParJoueur(plugin, joueur.getName()) > plugin.getConfig().getInt("Limit-map-by-player")) + if(joueur.hasPermission("imageonmap.nolimit")) { - joueur.sendMessage(ChatColor.RED +"ERROR: cannot render "+ nbImage +" picture(s): the limit of maps allowed for you (per player) would be exceeded."); - return; + + } + else + { + if (plugin.getConfig().getInt("Limit-map-by-player") != 0 && nbImage + ImgUtility.getNombreDeMapsParJoueur(plugin, joueur.getName()) > plugin.getConfig().getInt("Limit-map-by-player")) + { + joueur.sendMessage(ChatColor.RED +"ERROR: cannot render "+ nbImage +" picture(s): the limit of maps allowed for you (per player) would be exceeded."); + return; + } } MapView carte; ArrayList restant = new ArrayList(); + short[] ids = new short[nbImage]; for (int i = 0; i < nbImage; i++) { if(nbImage == 1 && joueur.getItemInHand().getType() == Material.MAP) @@ -74,11 +87,16 @@ public class TacheTraitementMap extends BukkitRunnable ImageRendererThread.SupprRendu(carte); carte.addRenderer(new Rendu(renduImg.getImg()[i])); map = new ItemStack(Material.MAP, 1, carte.getId()); - if(nbImage > 1 && renamed == true) + if(nbImage > 1) { - ItemMeta meta = map.getItemMeta(); - meta.setDisplayName("Map (" +renduImg.getNumeroMap().get(i) +")"); - map.setItemMeta(meta); + ids[i] = carte.getId(); + if(renamed == true) + { + ItemMeta meta = map.getItemMeta(); + meta.setDisplayName("Map (" +renduImg.getNumeroMap().get(i) +")"); + map.setItemMeta(meta); + } + } if(nbImage == 1 && joueur.getItemInHand().getType() == Material.MAP) @@ -91,10 +109,18 @@ public class TacheTraitementMap extends BukkitRunnable svg.SaveMap(); joueur.sendMap(carte); } + SavedPoster poster; + if(nbImage > 1) + { + poster = new SavedPoster(plugin, ids, joueur.getName()); + poster.Save(); + joueur.sendMessage("Poster ( Id: "+ poster.getId()+ " ) finished"); + } + else + joueur.sendMessage("Render finished"); if(!restant.isEmpty()) joueur.sendMessage(restant.size()+ " maps can't be place in your inventory. Please make free space in your inventory and run "+ ChatColor.GOLD+ "/maptool getrest"); plugin.setRemainingMaps(joueur.getName(), restant); - joueur.sendMessage("Render finished"); } }