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

Sala

Aventurier
27 Février 2021
23
0
3
18
Bonjour,
J'ai commencé à faire un plugin Loup-Garou UHC (mods de jeux du Loup-Garou mais dans Minecraft sous forme d'UHC) et j'ai essayé de faire les rôles avec un random que j'utilisais pour la téléportation en début de partie. Cependant, en faisant ça je ne sais pas comment affiché la liste des Loups-Garous à l'annonce des rôles (pour que les joueurs loup voit les pseudos des autres Loups).
Merci de m'aider si vous avez une idée de comment faire.
PS : J'ai fait des recherches un peu partout et j'ai rien trouvé à chaque fois...
Une partie du code du random :
1614439434375.png
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 135
162
463
247
21
Mìlhüsa
Bonjour,

Je ne sais pas ce que tu essayes de faire avec tous tes int, mais le rôle de tous tes joueurs tiennent dans une seule variable.
Ce serait plus intéressant dans ton cas d'utiliser des énumérations :
Java:
public enum Group {
   WEREWOLVES("Vous devez tuer tous les villageois."),
   VILLAGERS("Vous devez tuer tous les loups.");
   
   public final String goal;
   
   private Group(String goal) {
      this.goal = goal;
   }
}
Java:
public enum Character {
   WEREWOLF(Group.WEREWOLVES, "Loup-garou"),
   
   VILLAGER(Group.VILLAGERS, "Villageois"),
   SEER(Group.VILLAGERS, "Voyante"),
   HUNTER(Group.VILLAGERS, "Chasseur"),
   CUPID(Group.VILLAGERS, "Cupidon"),
   WITCH(Group.VILLAGERS, "Sorcière"),
   LITTLE_GIRL(Group.VILLAGERS, "Petite fille"),
   SHERIFF(Group.VILLAGERS, "Maire"),
   THIEF(Group.VILLAGERS, "Voleur");
   
   public final Group group;
   public final String name;
   
   private Character(Group group, String name) {
      this.group = group;
      this.name = name;
   }
   
   public boolean isWerewolf() {
      return group == Group.WEREWOLVES;
   }
   
   public boolean isVillager() {
      return group == Group.VILLAGERS;
   }
}

En soit les énumérations sont représentées par des int, c'est juste que les valeurs sont nommées.
Java:
Character character = Character.WITCH;
int index = character.ordinal();

Character bis = Character.values()[index];

System.out.println(character == bis);  // true
System.out.println(character.name());  // WITCH
System.out.println(bis.name());        // WITCH

Ensuite, pour associer un personnage/rôle à chaque joueur, il faut utiliser une Map<Player, Character>. C'est comme une liste/un tableau, sauf qu'au lieu de récupérer un élément avec son indice, on récupère un Character à partir d'un Player.
Maintenant pour associer un rôle à chaque joueur, le principe est de créer un jeu de cartes virtuel, de mélanger celui-ci puis de prendre les cartes dans l'ordre.
La difficulté réside dans le fait qu'il n'y a pas de vraie règle dans Les Loups-garous de Thiercelieux pour choisir les cartes, c'est au feeling, donc c'est à toi de chercher quelles cartes prendre en fonction du nombre de joueurs.

Un exemple de fonction pour associer un rôle à 8 joueurs :
Java:
public static Map<Player, Character> dealCharacters(Collection<? extends Player> players) {
	if(players.size() != 8) {
		throw new UnsupportedOperationException("Uh uh");
	}
	
	// notre jeu de cartes
	List<Character> cards = new LinkedList<>();
	
	for(int l = 0; l < 2; ++l)
		cards.add(Character.WEREWOLF); // 2 loups
	
	for(int v = 0; v < 5; ++v)
		cards.add(Character.VILLAGER); // 5 villageois
	
	cards.add(Character.SEER); // une voyante
	
	
	// on mélange nos cartes
	Collections.shuffle(cards);
	
	// on créer notre association Joueur <=> Rôle
	Map<Player, Character> map = new HashMap<>(8); // on préalloue la place pour 8 joueurs
	
	// pour chaque joueur
	for(Player player : players) {
		Character character = cards.remove(0); // on prend la première carte
		
		map.put(player, character); // on associe au joueur la carte
	}
	
	// return
	return  map;
}
Java:
Map<Player, Character> players = dealCharacters(Bukkit.getOnlinePlayers());

// pour récupérer le rôle d'un joueur :
Player player = ...;
Character character = players.get(player);

// pour récupérer tous les loups-garous :
List<Player> werewolfs = new ArrayList<>();
for(Map.Entry<Player, Character> entry : players.entrySet()) {
	Player player = entry.getKey();
	Character character = entry.getValue();
	
	if(character.isWerewolf()) {
		werewolfs.add(player);
	}
}

// autre version:
List<Player> werewolfs =
	players.entrySet()
		   .stream()
		   .filter(entry -> entry.getValue().isWerewolf())
		   .map(Map.Entry::getKey)
		   .collect(Collectors.toList());

// pour le message d'introduction :
for(Map.Entry<Player, Character> entry : players.entrySet()) {
	Player player = entry.getKey();
	Character character = entry.getValue();
	
	player.sendMessage("Vous êtes " + character.name);
	player.sendMessage(character.group.goal);
	
	if(character.isWerewolf()) {
		String names = werewolfs.stream().filter(p -> p != player).map(Player::getDisplayName).collect(Collectors.joining(", "));
		
		player.sendMessage("Pseudonymes des autres loups : " + names);
	}
}

Pour résumé : tu t'y prends mal, tu dois séparer l'endroit où tu associes à chaque joueur un rôle et l'endroit où tu dis aux joueurs quels rôles ils ont. Difficile de dire qui sont les autres loups si tous les joueurs n'ont pas encore de rôle.

Cordialement,
ShE3py
 

Sala

Aventurier
27 Février 2021
23
0
3
18
Juste une question : Tous ça, ça forme le plugin ?
Et sinon dans le dernier screen jsp quoi mettre à la place des ... dans Player player = ...;
 
Dernière édition:

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 135
162
463
247
21
Mìlhüsa
Juste une question : Tous ça, ça forme le plugin ?
Je ne sais pas trop ce que tu entends par là, mais oui ça forme une partie du plugin, mais il manque encore beaucoup de choses telles que le moteur de jeu (gérer le cycle jour/nuit jusqu'à ce qu'un camp à gagner).

Et sinon le dernier screen et l'avant avant dernier ne marche pas (enfin je ne sais pas dans quel classe les mettre plutot)
Ce ne sont pas vraiment des screenshots mais plutôt des morceaux de code. L'antépénultième (l'avant-avant-dernier) était pour te montrer qu'une énumération c'est plus ou moins la même chose qu'un int, et le dernier ne compile pas et c'est normal, c'est à toi de mettre les parties que tu veux où tu veux.
Si à un moment tu veux récupérer la liste des loups-garous bah tu prends le code, sinon tu le prends pas.

L'idée n'est pas de tout faire à ta place, le jeu n'est pas très facile à programmer. Tu peux aussi essayer de faire si tu veux un blackjack avant, les règles sont plutôt simples et bien décrites, et ça t'aideras à structurer après ton plugin.
 

Sala

Aventurier
27 Février 2021
23
0
3
18
ok ok mais pour le dernier le Player player = ...; je ne sais pas trop quoi mettre à la place du ... XD
et mrc aussi pour les bouts de code ça m'aide vachement (comparé à ce que j'avais fait au début...)
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 135
162
463
247
21
Mìlhüsa
ok ok mais pour le dernier le Player player = ...; je ne sais pas trop quoi mettre à la place du ... XD
Java:
Map<Player, Character> players = dealCharacters(Bukkit.getOnlinePlayers());

// pour récupérer le rôle d'un joueur :
Player player = ...;
Character character = players.get(player);
J'ai mis des points de suspension parce que le morceau de code permet de récupérer le rôle d'un joueur ; comment le joueur est récupéré n'importe peu.

Si par exemple les villageois tuent un joueur et que tu veux dire le rôle du joueur tué, ça ressemblera à ça :
Java:
Player player = Bukkit.getPlayer("Bernard");
Character character = players.get(player);

for(Player p : Bukkit.getOnlinePlayers()) {
	p.sendMessage("Bernard était: " + character.name);
}

Ensuite, ce que je te conseille c'est de créer une classe pour représenter une partie :
Java:
public class Game {
	// les joueurs dans la partie
	private final List<Player> players;
	
	// les personnages des joueurs
	private final Map<Player, Character> characters;
	
	// constructeur
	public Game(List<Player> players) {
		this.players = players;
		this.characters = dealCharacters(player);
	}
	
	private static Map<Player, Character> dealCharacters(Collection<? extends Player> players) {
		[...]
	}
	
	// pour récupérer les joueurs dans la partie
	public List<Player> getPlayers() {
		return Collections.unmodifiableList(players); // empêche de faire game.getPlayers().add(newPlayer)
	}
	
	// pour récupérer le rôle d'un joueur
	public Character getPlayerCharacter(Player player) {
		return characters.get(player);
	}
}

Comme ça tu pourras avoir plusieurs parties en même temps, chaque partie contenant les variables nécessaires pour la partie.
 

Btlgeuse

Aventurier
7 Février 2024
16
0
1
22
@ShE3py
J'ai bien lu et compris cela mais cependant j'ai un problème pour associer la répartition avec un Timer, par exemple pour avoir les rôles à 20 min
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 135
162
463
247
21
Mìlhüsa
Bonjour,

Tu peux utiliser un truc dans ce style :
Java:
public class MyPlugin extends JavaPlugin implements Listener {
  private ScheduledExecutorService scheduler;
  private Future<?> start;
 
  @Override
  public void onEnable() {
    this.scheduler = Executors.newSingleThreadScheduledExecutor(target -> new Thread(target, this.getName() + " Scheduler"));
   
    this.getServer().getPluginManager().registerEvents(this, this);
  }
 
  private void start() {
    this.getServer().broadcastMessage("La partie a commencée.");
  }
 
  @EventHandler
  public void onPlayerJoin(PlayerJoinEvent e) {
    if(this.start != null && !this.start.cancel(false)) {
      // La partie a déjà commencée.
      return;
    }
   
    this.start = this.scheduler.schedule(this::start, 20, TimeUnit.MINUTES);
  }
}

Cf. la Javadoc :
https://docs.oracle.com/en/java/jav....Runnable,long,java.util.concurrent.TimeUnit)

Cordialement,
ShE3py
 

Btlgeuse

Aventurier
7 Février 2024
16
0
1
22
Bonjour,

Tu peux utiliser un truc dans ce style :
Java:
public class MyPlugin extends JavaPlugin implements Listener {
  private ScheduledExecutorService scheduler;
  private Future<?> start;
 
  @Override
  public void onEnable() {
    this.scheduler = Executors.newSingleThreadScheduledExecutor(target -> new Thread(target, this.getName() + " Scheduler"));
  
    this.getServer().getPluginManager().registerEvents(this, this);
  }
 
  private void start() {
    this.getServer().broadcastMessage("La partie a commencée.");
  }
 
  @EventHandler
  public void onPlayerJoin(PlayerJoinEvent e) {
    if(this.start != null && !this.start.cancel(false)) {
      // La partie a déjà commencée.
      return;
    }
  
    this.start = this.scheduler.schedule(this::start, 20, TimeUnit.MINUTES);
  }
}

Cf. la Javadoc :
https://docs.oracle.com/en/java/jav....Runnable,long,java.util.concurrent.TimeUnit)

Cordialement,
ShE3py

Bonjour,
J'ai déjà un truc du style pour lancer la partie et avoir un timer mais mon problème c'est de relier la répartition des rôles similaires avec ce que t'as fait ci-dessus avec l'annonce du PvP. Est ce que je dois mettre le public static map après l'annonce du pvp ou je dois relier la classe game où j'ai mis la répartition des rôles et la classe game cycle qui me sert à activer le pvp