Changer la valeur d'une variable dans le config.yml

LEZIKO

Architecte en herbe
2 Novembre 2021
93
2
69
19
Bonjour/Bonsoir,

J'arrive vers la fin de la création d'un skywars mais j'ai un petit soucis: Le compteur de kills, il fonctionne à chaque partie se reset et tout est bon (je l'ai fait via une hashmap). J'aimerais quand même enregistrer les scores des joueurs dans le fichier de config, seulement quand je fais mon config.set il me set les nouveaux scores mais j'aimerais qu'il me les ajoutes et non les remplaces aux scores des joueurs, seulement je n'y arrive pas.

Pourriez-vous m'aider svp ?

LEZIKO
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 129
162
461
247
21
Mìlhüsa
Bonsoir,

Je n'ai pas compris si tu voulais sauvegarder la somme de l'ancienne et de la nouvelle valeur ou faire un historique de valeurs ?

Cordialement,
ShE3py
 

LEZIKO

Architecte en herbe
2 Novembre 2021
93
2
69
19
Bonjour,

Enfaite je souhaiterais juste faire un historique, exemple première partie je fais 3 kills dans la config il me met 3 kils deuxième partie je fais 2 kills dans la config il m'affiche 5 kills dans la 3eme partie je fais 5 kills, dans la config il m'affiche 10 kills ... En gros faire que ça s'accumule pour avoir le nombre total de kills d'un joueur.

LEZIKO
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 129
162
461
247
21
Mìlhüsa
Il te suffit de diversifier la clef principale avec la date ou un nombre ; game.0.kills.
Par contre il serait mieux de sauvegarder ça dans un autre fichier que « config.yml » puisque ce n'est pas de la configuration, et de sauvegarder par partie puis par joueur au lieu de par joueur puis par partie.
 

LEZIKO

Architecte en herbe
2 Novembre 2021
93
2
69
19
Il te suffit de diversifier la clef principale avec la date ou un nombre ; game.0.kills.
Par contre il serait mieux de sauvegarder ça dans un autre fichier que « config.yml » puisque ce n'est pas de la configuration, et de sauvegarder par partie puis par joueur au lieu de par joueur puis par partie.
hello ! merci de ta réponse et aurais-tu une technique pour faire tout ça ? j'ai jamais fait dcp j'ai pas vraiment d'idée
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 129
162
461
247
21
Mìlhüsa
Ça dépend de comment est structurer ton code, normalement tu devrais avoir une classe pour représenter une instance de mini-jeu et il te suffit d'y ajouter des fonctions pour sauvegarder et charger ;
Java:
public class GameInstance {
   private static final AtomicInteger LAST_ID = new AtomicInteger(0);
   private static final String FILENAME = "internal/GameInstances.dat";
   private static final Map<Integer, GameInstance> INSTANCES = new HashMap<>();
   private final int id;
   private final Set<UUID> players;
   private final Map<UUID, Integer> stats;
   
   public GameInstance() {
      this.id = LAST_ID.incrementAndGet();
      this.players = new HashSet<>();
      this.stats = new HashMap<>();
      
      INSTANCES.put(this.id, this);
   }
   
   private GameInstance(int id, Set<UUID> players, Map<UUID, Integer> stats) {
      this.id = id;
      this.players = players;
      this.stats = stats;
      
      INSTANCES.put(this.id, this);
   }
   
   public static void loadAll(JavaPlugin plugin) {
      YamlConfiguration config = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), FILENAME));
      
      Set<String> keys = config.getKeys(false);
      for(String key : keys) {
         final int id;
         try {
            id = Integer.parseInt(key);
            
            if(id <= 0) {
               throw new NumberFormatException();
            }
         }
         catch(NumberFormatException ignored) {
            plugin.getLogger().warning("GameInstances: invalid key `" + key + '`');
            continue;
         }
         
         LAST_ID.updateAndGet(prev -> Math.max(id, prev));
         try {
            load(config, id);
         }
         catch(Exception e) {
            plugin.getLogger().severe("GameInstances: unable to load key `" + key + '`');
         }
      }
   }
   
   @SuppressWarnings({ "unchecked", "ConstantConditions" })
   private static GameInstance load(YamlConfiguration config, int id) {
      ConfigurationSection section = config.getConfigurationSection(String.valueOf(id));
      Set<UUID> players = (Set<UUID>) section.get("players");
      Map<UUID, Integer> stats = (Map<UUID, Integer>) section.get("stats");
      
      return new GameInstance(id, players, stats);
   }
   
   public static void saveAll(JavaPlugin plugin) {
      YamlConfiguration config = new YamlConfiguration();
      for(GameInstance instance : INSTANCES.values()) {
         instance.saveInto(config);
      }
      
      try {
         config.save(new File(plugin.getDataFolder(), FILENAME));
      }
      catch(IOException e) {
         plugin.getLogger().log(Level.SEVERE, "GameInstances: unable to save on disk", e);
      }
   }
   
   private void saveInto(YamlConfiguration config) {
      ConfigurationSection section = config.createSection(String.valueOf(this.id));
      section.set("players", this.players);
      section.set("stats", this.stats);
   }
   
   public int getId() {
      return this.id;
   }
   
   public boolean addPlayer(UUID playerId) {
      return this.players.add(playerId);
   }
   
   public boolean addPlayer(Player player) {
      return this.addPlayer(player.getUniqueId());
   }
   
   public boolean removePlayer(UUID playerId) {
      return this.players.remove(playerId);
   }
   
   public boolean removePlayer(Player player) {
      return this.removePlayer(player.getUniqueId());
   }
   
   @UnmodifiableView
   public Set<UUID> playerIds() {
      return Collections.unmodifiableSet(this.players);
   }
   
   public Stream<OfflinePlayer> offlinePlayers() {
      return this.players.stream().map(Bukkit::getOfflinePlayer);
   }
   
   public Stream<Player> onlinePlayers() {
      return this.players.stream().map(Bukkit::getPlayer).filter(Objects::nonNull);
   }
   
   public int incrementKillsFor(Player player) {
      if(!this.players.contains(player.getUniqueId())) {
         throw new IllegalArgumentException("Cannot increment stats for someone does not participate in this GameInstance");
      }
      
      return this.stats.compute(player.getUniqueId(), (playerId, currentVal) -> ((currentVal == null) ? 1 : currentVal + 1));
   }
   
   public int getKillsFor(UUID playerId) {
      return this.stats.getOrDefault(playerId, 0);
   }
   
   public int getKillsFor(Player player) {
      return this.getKillsFor(player.getUniqueId());
   }
}
Java:
public class PlaygroundPlugin extends JavaPlugin implements Listener {
   @Override
   public void onEnable() {
      GameInstance.loadAll(this);
   }
   
   @Override
   public void onDisable() {
      GameInstance.saveAll(this);
   }
}

Pour éviter de perdre des données il faudrait rajouter une variable pour ne pas sauvegarder si jamais le fichier n'a pas été chargé (si tu as une exception dans ton onEnable(), il se peut que tu n'aies pas encore chargé le fichier entièrement, mais Bukkit appellera quand même le onDisable() de ton plugin, ce qui resauvegardera partiellement le fichier).

De la même façon si le serveur s'arrête brutalement pendant une sauvegarde, la mémoire sera libérée et le fichier sur le disque dur ne sera probablement pas entier, donc généralement pour sauvegarder dans un fichier A, l'on sauvegarde dans A.tmp, puis une fois que tout a été écrit on supprime A puis on renomme A.tmp en A ; il faut donc aussi gérer le cas où A.tmp existe mais pas A au chargement (arrêt pendant le renommage).
 

LEZIKO

Architecte en herbe
2 Novembre 2021
93
2
69
19
Ça dépend de comment est structurer ton code, normalement tu devrais avoir une classe pour représenter une instance de mini-jeu et il te suffit d'y ajouter des fonctions pour sauvegarder et charger ;
Java:
public class GameInstance {
   private static final AtomicInteger LAST_ID = new AtomicInteger(0);
   private static final String FILENAME = "internal/GameInstances.dat";
   private static final Map<Integer, GameInstance> INSTANCES = new HashMap<>();
   private final int id;
   private final Set<UUID> players;
   private final Map<UUID, Integer> stats;
  
   public GameInstance() {
      this.id = LAST_ID.incrementAndGet();
      this.players = new HashSet<>();
      this.stats = new HashMap<>();
     
      INSTANCES.put(this.id, this);
   }
  
   private GameInstance(int id, Set<UUID> players, Map<UUID, Integer> stats) {
      this.id = id;
      this.players = players;
      this.stats = stats;
     
      INSTANCES.put(this.id, this);
   }
  
   public static void loadAll(JavaPlugin plugin) {
      YamlConfiguration config = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), FILENAME));
     
      Set<String> keys = config.getKeys(false);
      for(String key : keys) {
         final int id;
         try {
            id = Integer.parseInt(key);
           
            if(id <= 0) {
               throw new NumberFormatException();
            }
         }
         catch(NumberFormatException ignored) {
            plugin.getLogger().warning("GameInstances: invalid key `" + key + '`');
            continue;
         }
        
         LAST_ID.updateAndGet(prev -> Math.max(id, prev));
         try {
            load(config, id);
         }
         catch(Exception e) {
            plugin.getLogger().severe("GameInstances: unable to load key `" + key + '`');
         }
      }
   }
  
   @SuppressWarnings({ "unchecked", "ConstantConditions" })
   private static GameInstance load(YamlConfiguration config, int id) {
      ConfigurationSection section = config.getConfigurationSection(String.valueOf(id));
      Set<UUID> players = (Set<UUID>) section.get("players");
      Map<UUID, Integer> stats = (Map<UUID, Integer>) section.get("stats");
     
      return new GameInstance(id, players, stats);
   }
  
   public static void saveAll(JavaPlugin plugin) {
      YamlConfiguration config = new YamlConfiguration();
      for(GameInstance instance : INSTANCES.values()) {
         instance.saveInto(config);
      }
     
      try {
         config.save(new File(plugin.getDataFolder(), FILENAME));
      }
      catch(IOException e) {
         plugin.getLogger().log(Level.SEVERE, "GameInstances: unable to save on disk", e);
      }
   }
  
   private void saveInto(YamlConfiguration config) {
      ConfigurationSection section = config.createSection(String.valueOf(this.id));
      section.set("players", this.players);
      section.set("stats", this.stats);
   }
  
   public int getId() {
      return this.id;
   }
  
   public boolean addPlayer(UUID playerId) {
      return this.players.add(playerId);
   }
  
   public boolean addPlayer(Player player) {
      return this.addPlayer(player.getUniqueId());
   }
  
   public boolean removePlayer(UUID playerId) {
      return this.players.remove(playerId);
   }
  
   public boolean removePlayer(Player player) {
      return this.removePlayer(player.getUniqueId());
   }
  
   @UnmodifiableView
   public Set<UUID> playerIds() {
      return Collections.unmodifiableSet(this.players);
   }
  
   public Stream<OfflinePlayer> offlinePlayers() {
      return this.players.stream().map(Bukkit::getOfflinePlayer);
   }
  
   public Stream<Player> onlinePlayers() {
      return this.players.stream().map(Bukkit::getPlayer).filter(Objects::nonNull);
   }
  
   public int incrementKillsFor(Player player) {
      if(!this.players.contains(player.getUniqueId())) {
         throw new IllegalArgumentException("Cannot increment stats for someone does not participate in this GameInstance");
      }
     
      return this.stats.compute(player.getUniqueId(), (playerId, currentVal) -> ((currentVal == null) ? 1 : currentVal + 1));
   }
  
   public int getKillsFor(UUID playerId) {
      return this.stats.getOrDefault(playerId, 0);
   }
  
   public int getKillsFor(Player player) {
      return this.getKillsFor(player.getUniqueId());
   }
}
Java:
public class PlaygroundPlugin extends JavaPlugin implements Listener {
   @Override
   public void onEnable() {
      GameInstance.loadAll(this);
   }
  
   @Override
   public void onDisable() {
      GameInstance.saveAll(this);
   }
}

Pour éviter de perdre des données il faudrait rajouter une variable pour ne pas sauvegarder si jamais le fichier n'a pas été chargé (si tu as une exception dans ton onEnable(), il se peut que tu n'aies pas encore chargé le fichier entièrement, mais Bukkit appellera quand même le onDisable() de ton plugin, ce qui resauvegardera partiellement le fichier).

De la même façon si le serveur s'arrête brutalement pendant une sauvegarde, la mémoire sera libérée et le fichier sur le disque dur ne sera probablement pas entier, donc généralement pour sauvegarder dans un fichier A, l'on sauvegarde dans A.tmp, puis une fois que tout a été écrit on supprime A puis on renomme A.tmp en A ; il faut donc aussi gérer le cas où A.tmp existe mais pas A au chargement (arrêt pendant le renommage).
Merci beaucoup j'vais regarder tout ça :)