Aide plugin pour rôle (lg uhc par ex)

java:
public class GGameCycle extends BukkitRunnable{

private GMain main;
private int timer = 60;

public GGameCycle(GMain main) {
this.main = main;
}

@Override
public void run() {


if(timer == 30 || timer == 15 || timer == 10 || timer == 5 || timer == 4 || timer == 3 || timer == 2 || timer == 1)
{
Bukkit.broadcastMessage("§ePvp activé dans " + timer + "s");

}

if(timer == 0)
{
cancel();
Bukkit.broadcastMessage("§1Pvp actif");

}



timer --;

}

}
j'ai ça comme game cycle
 
Dernière édition:
Là tu comptes des ticks sauf qu'un tick n'a pas vraiment de durée réelle (théoriquement un vingtième de seconde, mais ça peut être plus ou moins si par ex. le serveur lag ou que le tickrate a été modifié avec /tick).

Tu peux d'ailleurs simplifier ta condition en si le nombre est divisible par ou inférieur à cinq ;
Java:
@Override
public void run() {
  if(countdown == 0) {
    this.cancel();
    Bukkit.broadcastMessage("§1Le JcJ vient de s'activer.");
  }
  
  // Toutes les 5 s = 100 ticks, ou toutes les secondes s'il reste moins de 5 s.
  if(countdown % 100 == 0 || (countdown < 100 && countdown % 20 == 0)) {
    Bukkit.broadcastMessage("§eLe JcJ s'activera dans " + (countdown / 20) + (countdown >= 40 ? " secondes." : " seconde."));
  }
  
  --countdown;
}
 
Là tu comptes des ticks sauf qu'un tick n'a pas vraiment de durée réelle (théoriquement un vingtième de seconde, mais ça peut être plus ou moins si par ex. le serveur lag ou que le tickrate a été modifié avec /tick).

Tu peux d'ailleurs simplifier ta condition en si le nombre est divisible par ou inférieur à cinq ;
Java:
@Override
public void run() {
  if(countdown == 0) {
    this.cancel();
    Bukkit.broadcastMessage("§1Le JcJ vient de s'activer.");
  }
 
  // Toutes les 5 s = 100 ticks, ou toutes les secondes s'il reste moins de 5 s.
  if(countdown % 100 == 0 || (countdown < 100 && countdown % 20 == 0)) {
    Bukkit.broadcastMessage("§eLe JcJ s'activera dans " + (countdown / 20) + (countdown >= 40 ? " secondes." : " seconde."));
  }
 
  --countdown;
}
Je vais modifier ça mais le plus important c'est de svaoir comment intégrer la répartition des rôles dans le timer pour le pvp
 
Bah mettre le code de répartition dans le if(countdown == 0) { ... } ?
Mettre ce code entier ci dessous
private static Map<Player, GCharacter> dealCharacters(Collection<? extends Player> players){
if(players.size() != 2) {
throw new UnsupportedOperationException("Nuh uh");
}

List<GCharacter> cards = new LinkedList<>();

cards.add(GCharacter.BLUE_DEMON);
cards.add(GCharacter.ELECTRIC_KNIGHT);
Collections.shuffle(cards);

Map<Player, GCharacter> map = new HashMap<>(8);

for(Player player : players) {
GCharacter character = cards.remove(0);

map.put(player, character);
}

List<Player> demons = new ArrayList<>();
for(Map.Entry<Player, GCharacter>entry : ((Map<Player, GCharacter>) players).entrySet()) {
Player player = entry.getKey();
GCharacter character = entry.getValue();

if(character.isDemon()) {
demons.add(player);
}
}


for(Map.Entry<Player, GCharacter> entry : ((Map<Player, GCharacter>) players).entrySet()) {
Player player = entry.getKey();
GCharacter character = entry.getValue();

player.sendMessage("§4Vous êtes " + character.name);
player.sendMessage(character.group.goal);

if(character.isDemon()) {
String names = demons.stream().filter(p -> p != player).map(Player::getDisplayName).collect(Collectors.joining(", "));

player.sendMessage("§cPseudonyme des autres démons : " + names);
}
}

return map;
}
ou juste mettre le

for(Map.Entry<Player, GCharacter> entry : ((Map<Player, GCharacter>) players).entrySet()) {
Player player = entry.getKey();
GCharacter character = entry.getValue();

player.sendMessage("§4Vous êtes " + character.name);
player.sendMessage(character.group.goal);

if(character.isDemon()) {
String names = demons.stream().filter(p -> p != player).map(Player::getDisplayName).collect(Collectors.joining(", "));

player.sendMessage("§cPseudonyme des autres démons : " + names);
}
}
@ShE3py

aussi est ce normal que les secondes soit super longue avec ton code
 
Dernière édition:
Tu devrais créer une classe pour représenter tes joueurs ainsi qu'une partie :
Java:
public enum CharacterKind {
  BLUE_DEMON,
  ELECTRIC_KNIGHT;
  
  /**
   * Renvoie ce {@linkplain CharacterKind} sous la forme d'un nom commun au singulier et de son article indéfini.
   */
  @Nls
  public String asCommonNounWithIndefiniteArticle() {
    return switch(this) {
      case BLUE_DEMON -> "un démon bleu";
      case ELECTRIC_KNIGHT -> "un chevalier électrique";
    };
  }
  
  public boolean isDemon() {
    return switch(this) {
      case BLUE_DEMON -> true,
      default -> false
    };
  }
}

public class GPlayer {
  public final UUID uuid;
  public final CharacterKind character;
  
  public GPlayer(UUID playerId, CharacterKind chara) {
    this.uuid = playerId;
    this.character = chara;
  }
  
  @Nullable
  public Player asPlayer() {
    return MyPlugin.instance.getServer().getPlayer(this.uuid);
  }
}

public class MyGame {
  private final List<GPlayer> players;
  
  public MyGame(Iterable<? extends Player> players) {
    Map<Player, CharacterKind> gplayers = dealCharacters(players);
    
    this.players = new ArrayList<>(gplayers.size());
    for(var entry : gplayers.entrySet()) {
      this.players.add(new GPlayer(entry.getKey().getUniqueId(), entry.getValue());
    }
  }
  
  @UnmodifiableView
  public List<GPlayer> getPlayers() {
    return Collections.unmodifiableList(this.players);
  }
  
  @Unmodifiable
  public List<GPlayer> getDemons() {
    return this.players.stream().filter(p -> p.character.isDemon()).toList();
  }
}

public class MyPlugin extends JavaPlugin implements Listener, BukkitRunnable {
  public static MyPlugin instance;
  private MyGame game;
  
  @Override
  public void onEnable() {
    MyPlugin.instance = this;
    
    // FIXME: aucun joueur à cette étape, faut déplacer le code au véritable début de la partie (style dans une commande)
    this.game = new MyGame(this.getServer().getOnlinePlayers());
    
    // FIXME: enregistrer les events + planifier `run()`
    ...
  }
  
  @Override
  public void run() {
    if(countdown == 0) {
      this.cancel();
      Bukkit.broadcastMessage("§1Le JcJ vient de s'activer.");
      // FIXME: activer le JcJ
      
      // les rôles ont déjà étés distribués, ici on les affiches juste une fois le PvP activée
      // (je suppose que c'est ça que tu voulais)
      for(GPlayer p : this.game.getPlayers()) {
        p.sendMessage("§4Vous êtes " + p.character.asCommonNounWithIndefiniteArticle());
        
        if(p.isDemon()) {
          switch(this.game.getDemons().size()) {
            case 0 -> p.sendMessage("§cIl n'y a pas d'autre démon.");
            case 1 -> p.sendMessage("§cL'autre démon est : " + this.game.getDemons().filter(q -> q != p).findFirst(p).get() + '.');
            default -> {
              String others = this.game.getDemons().filter(q -> q != p).map(Player::getDisplayName).collect(Collectors.joining(", "));
              p.sendMessage("§cLes autres démons sont : " + others + '.');
            }
          };
        }
      }
    }
    
    // FIXME: suite du code
    ...
  }
}

aussi est ce normal que les secondes soit super longue avec ton code
J'ai supposé que ta fonction était appelée tous les ticks, mais effectivement si t'as mit tous les 20 ticks faudrait tout diviser par 20.

P.S.: Tu peux utiliser le markdown pour formater et colorer du source source :
Markdown (GitHub flavored):
```java
code source
```
 
Tu devrais créer une classe pour représenter tes joueurs ainsi qu'une partie :
Java:
public enum CharacterKind {
  BLUE_DEMON,
  ELECTRIC_KNIGHT;
 
  /**
   * Renvoie ce {@linkplain CharacterKind} sous la forme d'un nom commun au singulier et de son article indéfini.
   */
  @Nls
  public String asCommonNounWithIndefiniteArticle() {
    return switch(this) {
      case BLUE_DEMON -> "un démon bleu";
      case ELECTRIC_KNIGHT -> "un chevalier électrique";
    };
  }
 
  public boolean isDemon() {
    return switch(this) {
      case BLUE_DEMON -> true,
      default -> false
    };
  }
}

public class GPlayer {
  public final UUID uuid;
  public final CharacterKind character;
 
  public GPlayer(UUID playerId, CharacterKind chara) {
    this.uuid = playerId;
    this.character = chara;
  }
 
  @Nullable
  public Player asPlayer() {
    return MyPlugin.instance.getServer().getPlayer(this.uuid);
  }
}

public class MyGame {
  private final List<GPlayer> players;
 
  public MyGame(Iterable<? extends Player> players) {
    Map<Player, CharacterKind> gplayers = dealCharacters(players);
  
    this.players = new ArrayList<>(gplayers.size());
    for(var entry : gplayers.entrySet()) {
      this.players.add(new GPlayer(entry.getKey().getUniqueId(), entry.getValue());
    }
  }
 
  @UnmodifiableView
  public List<GPlayer> getPlayers() {
    return Collections.unmodifiableList(this.players);
  }
 
  @Unmodifiable
  public List<GPlayer> getDemons() {
    return this.players.stream().filter(p -> p.character.isDemon()).toList();
  }
}

public class MyPlugin extends JavaPlugin implements Listener, BukkitRunnable {
  public static MyPlugin instance;
  private MyGame game;
 
  @Override
  public void onEnable() {
    MyPlugin.instance = this;
  
    // FIXME: aucun joueur à cette étape, faut déplacer le code au véritable début de la partie (style dans une commande)
    this.game = new MyGame(this.getServer().getOnlinePlayers());
  
    // FIXME: enregistrer les events + planifier `run()`
    ...
  }
 
  @Override
  public void run() {
    if(countdown == 0) {
      this.cancel();
      Bukkit.broadcastMessage("§1Le JcJ vient de s'activer.");
      // FIXME: activer le JcJ
    
      // les rôles ont déjà étés distribués, ici on les affiches juste une fois le PvP activée
      // (je suppose que c'est ça que tu voulais)
      for(GPlayer p : this.game.getPlayers()) {
        p.sendMessage("§4Vous êtes " + p.character.asCommonNounWithIndefiniteArticle());
      
        if(p.isDemon()) {
          switch(this.game.getDemons().size()) {
            case 0 -> p.sendMessage("§cIl n'y a pas d'autre démon.");
            case 1 -> p.sendMessage("§cL'autre démon est : " + this.game.getDemons().filter(q -> q != p).findFirst(p).get() + '.');
            default -> {
              String others = this.game.getDemons().filter(q -> q != p).map(Player::getDisplayName).collect(Collectors.joining(", "));
              p.sendMessage("§cLes autres démons sont : " + others + '.');
            }
          };
        }
      }
    }
  
    // FIXME: suite du code
    ...
  }
}


J'ai supposé que ta fonction était appelée tous les ticks, mais effectivement si t'as mit tous les 20 ticks faudrait tout diviser par 20.

P.S.: Tu peux utiliser le markdown pour formater et colorer du source source :
Markdown (GitHub flavored):
```java
code source
```
J'avais une enum pour les group et une pour les rôles + une classe game que je t'avais montré ci dessus. Dois je tout supprimer ou simplement modifié certaines choses ?
Et j'ai un auto start donc le this.game = new game, je dois le mettre là ?
PS : merci infiniment de l'aider
 
Tu n'as pas détaillé ton jeu ni envoyé ta classe jeu donc j'essaye de trouver un modèle pratique, mais si tu veux tu as trois paradigmes classiques :
  • Java idiomatique (la manière traditionnelle de programmer en Java) :
    Java:
    public enum Reign {
      DEMON("les démons"), KNIGHT("les chevaliers");
    
      /**
       * Groupe nominal masculin pluriel défini.
       */
      public final String noun;
    
      Reign(String noun) {
        this.noun = noun;
      }
    }
    
    public enum Species {
      BLUE_DEMON(Reign.DEMON, "un démon bleu"),
      ELECTRIC_KNIGHT(Reign.KNIGHT, "un chevalier électrique");
    
      /**
       * Le règne de cette espèce.
       */
      public final Reign reign;
    
      /**
       * Groupe nominal masculin singulier indéfini.
       */
      public final Strign noun;
    
      Species(Reign reign, String noun) {
        this.reign = reign;
        this.noun = noun;
      }
    }

  • Programmation fonctionnelle :
    Java:
    public enum Reign {
      DEMON, KNIGHT;
     
      public String asNoun() {
        return switch(this) {
          case DEMON -> "les démons";
          case KNIGHT -> "les chevaliers";
        };
      }
    }
    
    public enum Species {
      BLUE_DEMON, ELECTRIC_KNIGHT;
     
      public Reign asReign() {
        return switch(this) {
          case BLUE_DEMON -> Reign.DEMON;
          case ELECTRIC_KNIGHT -> Reign.KNIGHT;
        };
      }
     
      public String asNoun() {
        return switch(this) {
          case BLUE_DEMON -> "un démon bleu";
          case ELECTRIC_KNIGHT -> "un chevalier électrique";
        };
      }
    }
    Le switch avec des flèches requiert Java 17, donc Minecraft 1.18+.

  • Programmation orientée objet :
    Java:
    public interface Reign {
      String asNoun();
    }
    
    public final class Demon implements Reign {
      @Override
      public String asNoun() {
        return "les démons";
      }
    }
    
    public final class Knight implements Reign {
      @Override
      public String asNoun() {
        return "les chevaliers";
      }
    }
    
    public interface Species {
      Reign asReign();
      String asNoun();
    }
    
    public abstract class DemonSpecies implements Species {
      @Override
      public final Reign asReign() {
        return Reign.DEMON;
      }
    }
    
    public abstract class KnightSpecies implements Species {
      @Override
      public final Reign asReign() {
        return Reign.KNIGHT;
      }
    }
    
    public class BlueDemon extends DemonSpecies {
      @Override
      public String asNoun() {
        return "un démon bleu";
      }
    }
    
    public class ElectricKnight extends KnightSpecies {
      @Override
      public String asNoun() {
        return "un chevalier électrique";
      }
    }

Les trois codes sont équivalents et c'est au choix du développeur. Donc pour répondre à ta question :
ois je tout supprimer ou simplement modifié certaines choses ?
Comme tu veux. Après j'écris le code dans un Notepad sans vérifier qu'il compile, donc tu as plutôt intérêt à comprendre mon code et à l'adapter à tes besoins. Le mieux pour moi serait de représenter une partie et un joueur d'une partie avec des classes, cf. GPlayer et MyGame de mon message précédent.

Et j'ai un auto start donc le this.game = new game, je dois le mettre là ?
Si tu veux je considère que MyGame représente une partie commencée (donc après un éventuel lobby), et à ce moment-là tous les joueurs ont déjà un rôle. Juste qu'il leur sera donné que 20 minutes après le début (une fois le JcJ activé). Donc une MyGame contiendra aussi sûrement un booléen pour représenter si le JcJ est actif ou non.
 
'''java :
package be.orion.minijeu;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.bukkit.entity.Player;

public class GGame {

public final List<GPlayer> players;
public final Map<GPlayer, GCharacter> characters;

public GGame(List<GPlayer> players) {
this.players = players;
Collection<? extends Player> player = null;
this.characters = dealCharacters(player);
}

public static Map<GPlayer, GCharacter> dealCharacters(Collection<? extends Player> players) {
if(players.size() != 2) {
throw new UnsupportedOperationException("Uh uh");
}

List<GCharacter> cards = new LinkedList<>();

cards.add(GCharacter.BLUE_DEMON);
cards.add(GCharacter.ELECTRIC_KNIGHT);

Collections.shuffle(cards);

Map<GPlayer, GCharacter> map = new HashMap<>(2);

for(Player player : players) {
GCharacter character = cards.remove(0);

map.put((GPlayer) player, character);
}

return map;
}

public List<GPlayer> getPlayers() {
return Collections.unmodifiableList(players);
}

public GCharacter getPlayerCharacter(GPlayer player) {
return characters.get(player);
}

} '''
Ma classe game
package be.orion.minijeu;

import java.util.UUID;

import org.bukkit.craftbukkit.libs.jline.internal.Nullable;
import org.bukkit.entity.Player;


public class GPlayer {
public final UUID uuid;
public final GCharacter character;

public GPlayer(UUID playerId, GCharacter chara) {
this.uuid = playerId;
this.character = chara;
}
@Nullable
public Player asPlayer(){
return GMain.instance.getServer().getPlayer(this.uuid);
}
public void sendMessage(String string) {
}
ma classe player
package be.orion.minijeu.tasks;

import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitRunnable;

import be.orion.minijeu.GGame;
import be.orion.minijeu.GMain;
import be.orion.minijeu.GPlayer;

public class GGameCycle extends BukkitRunnable{

private GMain main;
private int countdown = 10;
private GGame game;

public GGameCycle(GMain main) {
this.main = main;
}

@Override
public void run() {

if(countdown == 0) {
this.cancel();
Bukkit.broadcastMessage("§1Le JcJ vient de s'activer.");
for(GPlayer player : this.game.getPlayers()) {
player.sendMessage("Vous êtes : " + player.character);
}

}
if(countdown == 5 || countdown == 4 || countdown == 3 || countdown == 2|| countdown == 1) {
Bukkit.broadcastMessage("§eLe JcJ s'activera dans " + countdown + " seconde.");

}


--countdown;
}
ma classe game cycle
package be.orion.minijeu.tasks;

import java.util.Arrays;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitRunnable;

import be.orion.minijeu.GGame;
import be.orion.minijeu.GMain;
import be.orion.minijeu.GState;
import be.orion.minijeu.scoreboard.Scoreboard;

public class GAutostart extends BukkitRunnable {

private int timer = 10;
private GMain main;
private GGame game;

public GAutostart(GMain main) {
this.main = main;
}

@Override
public void run() {


for(Player pls : main.getPlayer()) {
pls.setLevel(timer);
}

if(timer == 10 || timer == 5 || timer == 4 || timer == 3 || timer == 2 || timer == 1)
{
Bukkit.broadcastMessage("§3Le jeux commencence dans " + timer + "s");
}

if(timer == 0)
{
Bukkit.broadcastMessage("§1Lancement du jeu");
main.setState(GState.Playing);

for(int i = 0; i < main.getPlayer().size(); i ++)
{
Player player = main.getPlayer().get(i);
Location spawn = main.getSpawns().get(i);
player.teleport(spawn);
player.getInventory().clear();
player.setFoodLevel(20);
player.setHealth(20);
player.updateInventory();

}


GGameCycle cycle = new GGameCycle(main);
cycle.runTaskTimer(main, 0, 20);

cancel();


}

timer--;

this.game = new GGame(this.getServer().getPlayers());

}

private GGame getServer() {
return null;
}

}
mon auto start
Et mon problème est que le jeux n'affiche pas le rôle donc je me demande si il est vraiment donné ou si le problème est juste le message avec le rôle pas envoyé
public class GMain extends JavaPlugin implements Listener {

public static GMain instance;
private GGame game;
private List<Player> players = new ArrayList<>();
private List<Location> spawns = new ArrayList<>();
private GState state;

@Override
public void onEnable() {
GMain.instance = this;
setState(GState.WAITING);

World world = Bukkit.getWorld("world");
spawns.add(new Location(world, 10, 80, -10.444, -90.3f, 36.5f));
spawns.add(new Location(world, -10, 80, 10, 90.9f, 74.9f ));
spawns.add(new Location(world, 10, 80, 10, 45f, 45f));
spawns.add(new Location(world, -10, 80, -10, -45f, -45f));
WorldBorder wb = world.getWorldBorder();
wb.setCenter(0, 0);
wb.setSize(100);

Bukkit.getScheduler().runTaskTimer(this, new Runnable() {

@Override
public void run() {
if(wb.getSize() >= 50) {
wb.setSize(wb.getSize()-1.0);
}

}
}, 0, 20);


PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new GPlayerListeners(this), this);
pm.registerEvents(new GDamageListeners(this), this);
}


public void setState(GState state) {
this.state = state;
}

public boolean isState(GState state) {
return this.state == state;
}

public List<Player> getPlayer(){
return players;
}

public List<Location> getSpawns(){
return spawns;
}

public void eliminate (Player player) {
if(players.contains(player))players.remove(player);
player.setGameMode(GameMode.SPECTATOR);
Bukkit.broadcastMessage(player.getName() + " est mort");
checkWin();
}


public void checkWin() {
if(players.size() == 1)
{
Player winner = players.get(0);
Bukkit.broadcastMessage(winner.getName() + " gagne le jeu ");
Bukkit.shutdown();
}

}
ma classe main par la meme occasion
+ j'ai rien mis dans mon playerlistener aà propos des roles ou de ggame
 
C'est des accents graves « ` » pour les blocs de code, donc probablement Alt gr 7 + Espace à taper (vu que par ex. Alt gr 7 + Maj A donne « À »). Après c'est plutôt pour les extraits de code, si tu envoies tout autant zipper le dossier dans une pièce jointe.

GGame.java
Java:
public final List<GPlayer> players;
public final Map<GPlayer, GCharacter> characters;

public GGame(List<GPlayer> players) {
    this.players = players;
    Collection<? extends Player> player = null;
    this.characters = dealCharacters(player);
}
Ça devrait crasher non ? Tu fais dealCharacters(null).

Diff:
 public final List<GPlayer> players;
-public final Map<GPlayer, GCharacter> characters;

 public GGame(List<GPlayer> players) {
-    this.players = players;
+    this.players = new ArrayList<>(players.size());
-    Collection<? extends Player> player = null;
-    this.characters = dealCharacters(player);
+    dealCharacters(players).forEach((player, character) -> this.players.add(new GPlayer(player.getUniqueId(), character)));
 }
(en rouge les lignes à enlever, en vert les lignes à rajouter, en blanc les lignes à laisser)
Un GPlayer contient déjà sa carte, donc pas besoin de Map<K, V>.

GAutostart.java
Java:
Player player = main.getPlayer().get(i);
Location spawn = main.getSpawns().get(i);
player.teleport(spawn);
player.getInventory().clear();
player.setFoodLevel(20);
player.setHealth(20);
player.updateInventory();
Tu devrais aussi réinitialiser l'expérience, les effets de potions, et le curseur du joueur (il me semble que si un joueur prend un item en main/dans sa souris, cet item n'est pas considéré comme étant dans son inventaire et il le gardera, à tester).

GMain.java
Diff:
 WorldBorder wb = world.getWorldBorder();
 wb.setCenter(0, 0);
 wb.setSize(100);
-
-Bukkit.getScheduler().runTaskTimer(this, new Runnable() {
-  @Override
-  public void run() {
-    if(wb.getSize() >= 50) {
-      wb.setSize(wb.getSize()-1.0);
-    }
-  }
-}, 0, 20);
+wb.setSize(50, 50);
Tu réinventes la roue. Renomme aussi GMain en style GPlugin car c'est un plugin, pas une classe principale.