Aller au contenu principal

API Donnees Joueur

Apprenez a travailler avec le systeme de stockage des donnees joueur de zMenu par programmation.

Vue d'Ensemble​

zMenu fournit un systeme de stockage de donnees integre qui persiste les valeurs specifiques aux joueurs. Ces donnees sont :

  • Stockees dans une base de donnees (SQLite, MySQL ou MariaDB)
  • Accessibles via des placeholders (%zmenu_player_value_<cle>%)
  • Persistantes apres les redemarrages du serveur
  • Disponibles via l'API

DataManager​

Obtenez le gestionnaire de donnees pour travailler avec les donnees joueur :

DataManager dataManager = menuPlugin.getDataManager();

Lire des Donnees​

Obtenir une Valeur Unique​

// Retourne Optional<String>
Optional<String> value = dataManager.getData(player, "coins");

// Verifier et utiliser la valeur
if (value.isPresent()) {
int coins = Integer.parseInt(value.get());
player.sendMessage("Vous avez " + coins + " pieces");
} else {
player.sendMessage("Aucune donnee de pieces trouvee");
}

Obtenir avec une Valeur par Defaut​

String coins = dataManager.getData(player, "coins").orElse("0");
int coinAmount = Integer.parseInt(coins);

Obtenir par UUID​

UUID uuid = player.getUniqueId();
Optional<String> value = dataManager.getData(uuid, "coins");

Verifier Si une Donnee Existe​

boolean hasCoins = dataManager.getData(player, "coins").isPresent();

Ecrire des Donnees​

Definir une Valeur​

// Definir une valeur de chaine
dataManager.setData(player, "coins", "100");

// Definir une valeur numerique (en tant que chaine)
dataManager.setData(player, "level", String.valueOf(5));

// Definir un booleen (en tant que chaine)
dataManager.setData(player, "premium", "true");

Ajouter a une Valeur Numerique​

// Ajouter 50 a la valeur actuelle
dataManager.addData(player, "coins", 50);

Soustraire d'une Valeur​

// Soustraire en ajoutant une valeur negative
dataManager.addData(player, "coins", -25);

Supprimer des Donnees​

// Supprimer une cle specifique pour un joueur
dataManager.removeData(player, "coins");

Operations en Masse​

Obtenir Toutes les Cles pour un Joueur​

// Cette fonctionnalite depend de l'implementation
// Generalement, vous suivriez vos propres cles
List<String> knownKeys = Arrays.asList("coins", "level", "premium", "last-login");

for (String key : knownKeys) {
dataManager.getData(player, key).ifPresent(value -> {
player.sendMessage(key + " : " + value);
});
}

Exemple Complet : Systeme de Monnaie​

package com.example.currency;

import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.DataManager;
import org.bukkit.entity.Player;

public class CurrencyManager {

private final DataManager dataManager;
private static final String COINS_KEY = "coins";

public CurrencyManager(MenuPlugin menuPlugin) {
this.dataManager = menuPlugin.getDataManager();
}

public int getCoins(Player player) {
return dataManager.getData(player, COINS_KEY)
.map(Integer::parseInt)
.orElse(0);
}

public void setCoins(Player player, int amount) {
dataManager.setData(player, COINS_KEY, String.valueOf(Math.max(0, amount)));
}

public void addCoins(Player player, int amount) {
int current = getCoins(player);
setCoins(player, current + amount);
}

public boolean removeCoins(Player player, int amount) {
int current = getCoins(player);
if (current >= amount) {
setCoins(player, current - amount);
return true;
}
return false;
}

public boolean hasCoins(Player player, int amount) {
return getCoins(player) >= amount;
}
}

Utilisation​

CurrencyManager currency = new CurrencyManager(menuPlugin);

// Verifier le solde
int balance = currency.getCoins(player);
player.sendMessage("Solde : " + balance);

// Ajouter des pieces
currency.addCoins(player, 100);
player.sendMessage("100 pieces ajoutees !");

// Retirer des pieces (avec verification)
if (currency.removeCoins(player, 50)) {
player.sendMessage("50 pieces depensees");
} else {
player.sendMessage("Pas assez de pieces !");
}

Exemple Complet : Suivi des Statistiques​

package com.example.stats;

import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.DataManager;
import org.bukkit.entity.Player;

public class StatsTracker {

private final DataManager dataManager;

public StatsTracker(MenuPlugin menuPlugin) {
this.dataManager = menuPlugin.getDataManager();
}

// Kills
public int getKills(Player player) {
return getIntValue(player, "kills");
}

public void incrementKills(Player player) {
dataManager.addData(player, "kills", 1);
}

// Morts
public int getDeaths(Player player) {
return getIntValue(player, "deaths");
}

public void incrementDeaths(Player player) {
dataManager.addData(player, "deaths", 1);
}

// Ratio K/D
public double getKDRatio(Player player) {
int kills = getKills(player);
int deaths = getDeaths(player);
if (deaths == 0) return kills;
return (double) kills / deaths;
}

// Temps de jeu (en minutes)
public long getPlaytime(Player player) {
return getLongValue(player, "playtime");
}

public void addPlaytime(Player player, long minutes) {
long current = getPlaytime(player);
dataManager.setData(player, "playtime", String.valueOf(current + minutes));
}

// Methodes utilitaires
private int getIntValue(Player player, String key) {
return dataManager.getData(player, key)
.map(Integer::parseInt)
.orElse(0);
}

private long getLongValue(Player player, String key) {
return dataManager.getData(player, key)
.map(Long::parseLong)
.orElse(0L);
}
}

Exemple Complet : Systeme de Recompenses Quotidiennes​

package com.example.rewards;

import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.DataManager;
import org.bukkit.entity.Player;

public class DailyRewardsManager {

private final DataManager dataManager;
private static final long DAY_IN_MILLIS = 24 * 60 * 60 * 1000;

public DailyRewardsManager(MenuPlugin menuPlugin) {
this.dataManager = menuPlugin.getDataManager();
}

public boolean canClaimDaily(Player player) {
long lastClaim = getLastClaimTime(player);
long now = System.currentTimeMillis();
return (now - lastClaim) >= DAY_IN_MILLIS;
}

public long getTimeUntilNextClaim(Player player) {
long lastClaim = getLastClaimTime(player);
long now = System.currentTimeMillis();
long nextClaim = lastClaim + DAY_IN_MILLIS;
return Math.max(0, nextClaim - now);
}

public void claimDaily(Player player) {
dataManager.setData(player, "daily-last-claim",
String.valueOf(System.currentTimeMillis()));
incrementStreak(player);
}

public int getStreak(Player player) {
return dataManager.getData(player, "daily-streak")
.map(Integer::parseInt)
.orElse(0);
}

private void incrementStreak(Player player) {
dataManager.addData(player, "daily-streak", 1);
}

public void resetStreak(Player player) {
dataManager.setData(player, "daily-streak", "0");
}

private long getLastClaimTime(Player player) {
return dataManager.getData(player, "daily-last-claim")
.map(Long::parseLong)
.orElse(0L);
}

// Formater le temps restant
public String formatTimeRemaining(Player player) {
long millis = getTimeUntilNextClaim(player);
long hours = millis / (60 * 60 * 1000);
long minutes = (millis % (60 * 60 * 1000)) / (60 * 1000);
return String.format("%dh %dm", hours, minutes);
}
}

Travailler avec des Donnees Complexes​

Pour des structures de donnees complexes, serialisez en JSON :

import com.google.gson.Gson;

public class ComplexDataManager {

private final DataManager dataManager;
private final Gson gson = new Gson();

public ComplexDataManager(MenuPlugin menuPlugin) {
this.dataManager = menuPlugin.getDataManager();
}

// Sauvegarder une liste
public void saveStringList(Player player, String key, List<String> list) {
String json = gson.toJson(list);
dataManager.setData(player, key, json);
}

// Charger une liste
public List<String> loadStringList(Player player, String key) {
return dataManager.getData(player, key)
.map(json -> gson.fromJson(json,
new TypeToken<List<String>>(){}.getType()))
.orElse(new ArrayList<>());
}

// Sauvegarder un objet personnalise
public void savePlayerStats(Player player, PlayerStats stats) {
String json = gson.toJson(stats);
dataManager.setData(player, "player-stats", json);
}

// Charger un objet personnalise
public PlayerStats loadPlayerStats(Player player) {
return dataManager.getData(player, "player-stats")
.map(json -> gson.fromJson(json, PlayerStats.class))
.orElse(new PlayerStats());
}
}

// Exemple de classe de donnees
public class PlayerStats {
public int kills = 0;
public int deaths = 0;
public long playtime = 0;
public List<String> achievements = new ArrayList<>();
}

Utiliser les Donnees dans les Inventaires​

Les donnees que vous definissez sont automatiquement disponibles en tant que placeholders :

items:
stats-display:
slot: 4
item:
material: PLAYER_HEAD
playerHead: "%player%"
name: "&6&lStatistiques de %player%"
lore:
- "&7Pieces : &e%zmenu_player_value_coins%"
- "&7Kills : &a%zmenu_player_value_kills%"
- "&7Morts : &c%zmenu_player_value_deaths%"
- "&7Serie : &b%zmenu_player_value_daily-streak%"

Bonnes Pratiques​

  1. Utiliser des noms de cles coherents - Etablir une convention de nommage
  2. Gerer les donnees manquantes - Toujours utiliser orElse() pour les valeurs par defaut
  3. Valider l'analyse numerique - Envelopper dans un try-catch pour la securite
  4. Ne pas ecraser les donnees importantes - Verifier avant de definir
  5. Utiliser les types de donnees appropries - Stocker en tant que chaines, analyser quand necessaire
  6. Nettoyer les donnees inutilisees - Supprimer les cles qui ne sont plus necessaires

Conventions de Nommage des Cles​

// Bonnes conventions de nommage
"coins" // Simple, clair
"daily-streak" // Kebab-case pour plusieurs mots
"quest-tutorial-1" // Inclure des identifiants
"stats-kills" // Prefixer avec la categorie

// A eviter
"c" // Trop court
"playerCoinsData" // CamelCase (utiliser kebab)
"x1y2z3" // Sans signification

Etapes Suivantes​

Copyright © 2026 GroupeZ|Build #loading...|-