Plugin Erreur de la SLAPI

LuckySpawn

Aventurier
21 Juillet 2020
7
0
2
France
Bonjour, je suis encore débutant en développement et j'aimerais avoir de l'aide car depuis l'ajout d'un sytème s'économie le plugin n'est plus fonctionnel :(
Ma classe principale
Java:
package fr.luckyspawn.hub;

import org.bukkit.command.CommandExecutor;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;

import fr.luckyspawn.hub.commands.AdminCommands;
import fr.luckyspawn.hub.commands.EconomyCommands;
import fr.luckyspawn.hub.commands.GamemodeCommands;
import fr.luckyspawn.hub.commands.InteractCommands;
import fr.luckyspawn.hub.commands.SpawnCommand;
import fr.luckyspawn.hub.HubListeners;
import fr.luckyspawn.hub.SLAPI;

public class Main
  extends JavaPlugin {
  public void onEnable() {
      System.out.println("Enable");
      SLAPI.loadBalances();
      getCommand("gamemenu").setExecutor((CommandExecutor)new InteractCommands());
      getCommand("shopmenu").setExecutor((CommandExecutor)new InteractCommands());
      getCommand("gameshopmenu").setExecutor((CommandExecutor)new InteractCommands());
      getCommand("pamenu").setExecutor((CommandExecutor)new InteractCommands());
      getCommand("profilmenu").setExecutor((CommandExecutor)new InteractCommands());
      getCommand("hubmenu").setExecutor((CommandExecutor)new InteractCommands());
      getCommand("preferencemenu").setExecutor((CommandExecutor)new InteractCommands());
      getCommand("bypass").setExecutor((CommandExecutor)new AdminCommands());
      getCommand("bp").setExecutor((CommandExecutor)new AdminCommands());
      getCommand("onjoin").setExecutor((CommandExecutor)new AdminCommands());
      getCommand("spawn").setExecutor((CommandExecutor)new SpawnCommand());
      getCommand("gm").setExecutor((CommandExecutor)new GamemodeCommands());
      getCommand("economy").setExecutor((CommandExecutor)new EconomyCommands());
      new Economy(this);
      getServer().getPluginManager().registerEvents(new EconomyListeners(), (Plugin)this);
      getServer().getPluginManager().registerEvents(new HubListeners(), (Plugin)this);
  }

  public void onDisable() {
      SLAPI.saveBalances();
      System.out.println("Finish");
  }
}

Classe principale du système d'économie
Java:
package fr.luckyspawn.hub;

import java.util.HashMap;

public class Economy {
    
    private static Main plugin;
    
    public Economy(Main instance) {
        plugin = instance;
    }
    
    public static HashMap<String, Double> balance =new HashMap<>();
    
    public static void setBalance(String player, double amount) {
        balance.put(player, amount);
    }
    public static Double getBalance (String player) {
        return balance.get(player);
    }
    
    public static boolean hasAccount(String player) {
        return balance.containsKey(player);
    }
    public static HashMap<String, Double> getBalanceMap(){
        return balance;
    }
    public static Main getPlugin() {
        return plugin;
    }
    
}
 

LuckySpawn

Aventurier
21 Juillet 2020
7
0
2
France
Le Listener de l'economie
Java:
package fr.luckyspawn.hub;

import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

public class EconomyListeners implements Listener{
    @EventHandler
    public void onJoin(PlayerJoinEvent event) {
        if(Economy.hasAccount(event.getPlayer().getName())) return;
        Economy.setBalance(event.getPlayer().getName(), 200D);
    }
}
Et enfin l'SLAPI, le problème viendrais sûrement de là !
Java:
package fr.luckyspawn.hub;

public class SLAPI {
  
    private static Main plugin = Economy.getPlugin();
  
    public static void saveBalances() {
        for(String p : Economy.getBalanceMap().keySet()) {
            plugin.getConfig().set("balance."+p, Economy.getBalanceMap().get(p));
        }
        plugin.saveConfig();
    }
    public static void loadBalances() {
        if(!plugin.getConfig().contains("balance")) return;
        for(String s : plugin.getConfig().getConfigurationSection("balance").getKeys(false)) {
            Economy.setBalance(s, plugin.getConfig().getDouble("balance."+s));
        }
    }
}
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 087
157
455
247
21
Mìlhüsa
Bonjour,

le plugin n'est plus fonctionnel
Si tu n'expliques pas plus, l'on a pas trop d'idée de ce que tu entends par « être fonctionnel » ou ne pas l'être.

Sinon, ton code n'est pas très propre :
Java:
// renomme Main en MonPlugin ou le nom de ton plugin (SLAPI)
// parce que sinon si tu cherches à dialoguer avec un autre plugin,
// tu auras 145 classes Main
public class Main
    // pas besoin de mettre un retour à la ligne,
    // ou au moins laisse une ligne vide après pour séparer
    extends JavaPlugin {
        
    // ajoute @Override :
    // 1. Si tu te trompes dans la fontion, tu as une erreur
    @Override
    public void onenable() {} // Method does not override method from its superclass
    
    @Override
    public String onEnable() {} // 'onDisable()' in 'fr.luckyspawn.hub.Main' clashes with 'onDisable()' in 'org.bukkit.plugin.java.JavaPlugin'; attempting to use incompatible return type
    
    // 2. Tu sais que la fonction est utilisée ailleurs que dans ton code, elle n'existerait pas sinon
    public void onEnable() {
        // le serveur affiche déjà 'Enabling MonPlugin v1.0.0' lorsqu'il appelle cette méthode
        // + n'utilise pas System.out ou System.err
        // mais le logger de ton plugin
        //
        // la console affichera [MonPlugin],
        // sinon difficile de savoir quel plugin dit quoi
        System.out.println("Enable");
        SLAPI.loadBalances();
        
        // RESPIRE !
        // sépare les parties, ne colle pas tout
        getCommand("gamemenu").setExecutor((CommandExecutor)new InteractCommands());
        getCommand("shopmenu").setExecutor((CommandExecutor)new InteractCommands());
        getCommand("gameshopmenu").setExecutor((CommandExecutor)new InteractCommands());
        getCommand("pamenu").setExecutor((CommandExecutor)new InteractCommands());
        getCommand("profilmenu").setExecutor((CommandExecutor)new InteractCommands());
        getCommand("hubmenu").setExecutor((CommandExecutor)new InteractCommands());
        getCommand("preferencemenu").setExecutor((CommandExecutor)new InteractCommands());
        getCommand("bypass").setExecutor((CommandExecutor)new AdminCommands());
        getCommand("bp").setExecutor((CommandExecutor)new AdminCommands());
        getCommand("onjoin").setExecutor((CommandExecutor)new AdminCommands());
        getCommand("spawn").setExecutor((CommandExecutor)new SpawnCommand());
        getCommand("gm").setExecutor((CommandExecutor)new GamemodeCommands());
        getCommand("economy").setExecutor((CommandExecutor)new EconomyCommands());
        // pas besoin de cast en (CommandExecutor),
        // c'est déjà un CommandExecutor
        
        new Economy(this);
        
        // pas besoin non plus de cast en (Plugin)
        getServer().getPluginManager().registerEvents(new EconomyListeners(), (Plugin)this);
        getServer().getPluginManager().registerEvents(new HubListeners(), (Plugin)this);
    }
    
    // idem, @Override
    public void onDisable() {
        SLAPI.saveBalances();
        System.out.println("Finish"); // idem, utilise le logger
    }
}

public class Economy {
    private static Main plugin;
    
    // un constructeur sert à se construire lui-même,
    // et non toute l'Economy
    public Economy(Main instance) {
        plugin = instance;
    }
    
    // utilise une fonction statique
    public static void setPlugin(Main plugin) {
        Economy.plugin = plugin;
    }
    
    // MAIS DANS TOUS LES CAS
    // ce n'est pas à Economy de stocker le plugin
    // tu dois le récupérer à partir de Main,
    // au lieu de le passer à travers toutes tes fonctions
    
    // met toutes les variables ensemble, et toutes les fonctions ensemble
    // là elle est un peu perdue
    public static HashMap<String, Double> balance =new HashMap<>();
    
    // les joueurs peuvent changer de nom,
    // alors ne stocke pas son nom en clef,
    // mais son UUID, qui est unique à chaque compte
    // et qui ne change pas même si le nom change
    
    // les nombres décimaux/réels (float, double) rencontrent des erreurs
    // au fur et à mesure des calculs, alors prend des nombres entiers (int, long)
    // si tu veux avoir des centimes, fait que ta variable compte les centimes,
    // et non directement les euros
    
    public static void setBalance(String player, double amount) {
        balance.put(player, amount);
    }
    
    public static Double getBalance (String player) {
        return balance.get(player);
    }
    
    // tous les joueurs ont un compte.
    public static boolean hasAccount(String player) {
        return balance.containsKey(player);
    }
    
    // attention:
    // l'on peut faire Economy.getBalanceMap().put("Foobar", Double.MAX_VALUE);
    public static HashMap<String, Double> getBalanceMap(){
        return balance;
    }
    
    public static Main getPlugin() {
        return plugin;
    }
    
}

public class EconomyListeners implements Listener {
    @EventHandler
    public void onJoin(PlayerJoinEvent event) {
        if(Economy.hasAccount(event.getPlayer().getName())) return;
        Economy.setBalance(event.getPlayer().getName(), 200D);
        
        // Tu donnes 200 d'argent si le joueur a déjà un compte.
        // À quel moment un compte est-il créé alors ?
    }
}

public class SLAPI {
    private static Main plugin = Economy.getPlugin();
    // tu passes par une classe qui récupère elle-même le plugin d'une autre classe.
    // de plus, tu met cette variable en statique
    // si SLAPI est initialisée avant la méthode onEnable,
    // Economy.getPlugin() == null
    
    // non, non et non
    // tu sauvegardes l'argent dès qu'il est modifié
    // pas seulement lorsque ton plugin s'arrête
    // parce que si le serveur crash 4 jours après s'être lancé,
    // si tu ne sauvegardes que lorsqu'il s'arrête normalement,
    // ces 4j sont perdus.
    public static void saveBalances() {
        for(String p : Economy.getBalanceMap().keySet()) {
            plugin.getConfig().set("balance."+p, Economy.getBalanceMap().get(p));
        }
        plugin.saveConfig();
    }
    
    public static void loadBalances() {
        if(!plugin.getConfig().contains("balance")) return;
        for(String s : plugin.getConfig().getConfigurationSection("balance").getKeys(false)) {
            Economy.setBalance(s, plugin.getConfig().getDouble("balance."+s));
        }
    }
    
    // et puis pourquoi c'est une autre classe qui s'occupe de sauvegarder la classe
    // chacun pour soit dans la vie
}

Une solution serait :
Java:
package fr.she3py.example;

import java.util.logging.Logger;

import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;

public class MyPlugin extends JavaPlugin {
    public static MyPlugin plugin;
    public static Logger logger;
    public static FileConfiguration config;
    
    @Override
    public void onEnable() {
        plugin = this;
        logger = this.getLogger();
        
        this.saveDefaultConfig();
        config = this.getConfig();
        
        logger.info("Loading balances...");
        Economy.load();
        
        logger.info("Registering commands...");
        this.getCommand("gamemenu").setExecutor(new InteractCommands());
        // ...
        
        logger.info("Registering listeners...");
        PluginManager pluginManager = this.getServer().getPluginManager();
        pluginManager.registerEvents(new EconomyListeners(), this);
        // ...
    }
}

package fr.she3py.example;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;

import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.util.NumberConversions;

public class Economy {
    private static final Map<UUID, Long> BALANCES = new HashMap<>();
    
    public static void setBalance(UUID playerId, long newValue) {
        // todo: check newValue range
        // newValue = Math.max(newValue, 0L);
        
        synchronized(BALANCES) {
            BALANCES.put(playerId, newValue);
        }
        
        MyPlugin.config.set("balance." + playerId.toString(), newValue);
        MyPlugin.plugin.saveDefaultConfig();
    }
    
    public static void setBalance(OfflinePlayer player, long newValue) {
        setBalance(player.getUniqueId(), newValue);
    }
    
    public static long getBalance(UUID playerId) {
        synchronized(BALANCES) {
            if(!BALANCES.containsKey(playerId))
                BALANCES.put(playerId, 0L);
            
            return BALANCES.get(playerId);
            
            // en une ligne :
            return BALANCES.computeIfAbsent(playerId, uuid -> 0L);
            
            // remplace 0L par l'argent par défaut
        }
    }
    
    public static long getBalance(OfflinePlayer player) {
        return getBalance(player.getUniqueId());
    }
    
//    @UnmodifiableView
    public static Map<UUID, Long> getBalanceMap() {
        // renvoit une Map immuable, sans pour autant la copier
        return Collections.unmodifiableMap(BALANCES);
    }
    
    public static void saveAll() {
        FileConfiguration config = MyPlugin.plugin.getConfig();
        
        for(Map.Entry<UUID, Long> entry : BALANCES.entrySet()) {
            config.set("balance." + entry.getKey().toString(), entry.getValue());
        }
        
        MyPlugin.plugin.saveConfig();
    }
    
    public static void load() {
        FileConfiguration config = MyPlugin.plugin.getConfig();
        
        ConfigurationSection section = config.getConfigurationSection("balance");
        if(section == null)
            return;
        
        synchronized(BALANCES) {
            BALANCES.clear();
            
            for(Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
                try {
                    UUID playerId = UUID.fromString(entry.getKey() /* .substring("balance.".length()) */);
                    long value = NumberConversions.toLong(entry.getValue());
                    
                    BALANCES.put(playerId, value);
                }
                catch(Exception e) {
                    MyPlugin.logger.log(Level.SEVERE, "Skipping entry '" + entry.getKey() + '=' + entry.getValue().toString() + '\'', e);
                }
            }
        }
    }
}


Cordialement,
ShE3py.
 

LuckySpawn

Aventurier
21 Juillet 2020
7
0
2
France
Bonjour, merci de votre aide ! En fait j'aimerais pouvoir avoir un seul et même plugin sur mon serveur (donc pour le choix des jeux, l'économie et les grades) mais l'économie ne fonctionne pas correctement même après avoir suivit un tutoriel détaillé. Mais je pense d'avoir d'ou provient l'erreur, en fait le tutoriel a été fait pour la version 1.6.4 de minecraft alors que moi je code en 1.9 compatible jusqu'à la 1.16, pourriez vous m'aider/m'expliquez comment créer un simple système d'économie (add/remove/set money) s'il-vous-plaît, merci de votre aide :D