Skip to content

Releases: Loutreee/StatCraft

2.3.1

07 Mar 08:31
Compare
Choose a tag to compare

##Fix some things

2.3.0

06 Mar 16:09
f7dcf57
Compare
Choose a tag to compare

1. Configuration et Intégration de l'API REST

  • Endpoints REST supplémentaires
    • Création d’un ScoreController avec :
      • /api/score/:playerName pour obtenir le score total d’un joueur.
      • /api/score/history/:playerName pour obtenir l’historique complet (tous les snapshots avec timestamp et score total) d’un joueur.
      • /api/scores pour récupérer l’historique des scores de tous les snapshots.

2. Gestion des Statistiques en Jeu et Calcul du Score

  • Gestion des événements du jeu :

    • Bloc miné : Événement BlockBreakEvent incrémente le compteur de blocs minés et ajoute des points selon la config.
    • Item crafté : Passage de PrepareItemCraftEvent à CraftItemEvent pour n’incrémenter le compteur qu’une fois l’item réellement crafté.
      • Gestion particulière du shift-click pour multiplier la quantité (ex. pour les sticks qui produisent 4 unités).
    • Mob tué : Événement EntityDeathEvent incrémente le compteur de mobs tués par un joueur et ajoute des points selon la config.
  • Calcul du score par catégorie :

    • Ajout dans la classe PlayerStats de champs pour chaque sous-score :
      • blockScore, craftScore, mobScore, et timeScore
    • Le totalScore est la somme de tous ces sous-scores.
    • Un point est attribué par minute de jeu (calculé via Statistic.PLAY_ONE_MINUTE).
  • Mise à jour des compteurs et scores :

    • À chaque action, en plus d'incrémenter le compteur (dans des maps pour blocs, items et mobs), le score correspondant est ajouté via des méthodes telles que addBlockScore(amount).
    • Les scores sont définis selon les valeurs présentes dans le fichier de config, accessibles via le ScoreService.

3. Snapshots et Persistance des Données

  • Insertion régulière de snapshots :

    • Une tâche planifiée (toutes les 30 secondes / 600 ticks) parcourt tous les joueurs connectés et insère un snapshot dans la collection "playerStatsSnapshots".
    • Chaque snapshot contient :
      • Les compteurs détaillés (maps de blocs minés, items craftés, mobs tués).
      • Le temps de jeu actuel.
      • Les sous-scores (blockScore, craftScore, mobScore, timeScore) et le totalScore.
      • Un timestamp (format ISO) pour tracer l’évolution dans le temps.
  • Insertion lors de la déconnexion :

    • Lors du PlayerQuitEvent, un snapshot est inséré immédiatement pour garantir que l’état final du joueur est sauvegardé.
    • Les données en mémoire pour le joueur sont ensuite supprimées pour libérer des ressources.
  • Restauration des statistiques depuis le dernier snapshot :

    • Lorsqu’un joueur se connecte, la méthode StatsManager.initializePlayerStats(Player) récupère le snapshot le plus récent (trié par timestamp) et restaure :
      • Les maps de statistiques (blocs, items, mobs).
      • Les sous-scores (blockScore, craftScore, mobScore, timeScore) et le totalScore.
    • Ceci assure une continuité des données et évite de repartir de zéro après un redémarrage ou une déconnexion.

4. Visualisation et API pour l’Historique

  • Leaderboard et graphique :

    • Un composant React LeaderboardChart récupère les snapshots via l’API REST.
    • Fusion et tri chronologique des snapshots :
      • Les snapshots sont fusionnés par timestamp (utilisation de la valeur ISO) et triés pour afficher des lignes continues.
      • Une imputation des valeurs manquantes est réalisée pour assurer une courbe continue, reliant chaque point dans le temps.
  • Modification du graphique :

    • Utilisation de <LineChart> avec dot={false} pour tracer des lignes continues reliant tous les points.
    • Correction pour que les données soient affichées dans l’ordre chronologique, en imputant la dernière valeur connue pour les joueurs absents dans un snapshot donné.
  • Routes API supplémentaires pour les scores :

    • Ajout d’un endpoint pour obtenir l’historique complet des scores d’un joueur (/api/score/history/:playerName).

5. Développement et Intégration Front-End

  • Intégration de l’application React :

    • L’application React est buildée et servie par Javalin à partir du dossier /web.
    • En développement, un proxy est configuré (ou CORS est géré proprement) pour que l’application React puisse accéder à l’API REST qui tourne dans le plugin.
    • Le composant PlayersList et PlayerStats ont été adaptés pour utiliser les endpoints API plutôt que des données statiques.
  • Exemple d’appel API dans PlayerStats :

    • Le composant récupère via fetch("/api/stats/{player}/latest") le snapshot le plus récent et affiche les informations clés (timestamp, temps de jeu, scores par catégorie et score total).
    • Un nouveau composant LeaderboardChart affiche l’évolution des scores dans un graphique linéaire continu.

2.2.0

28 Feb 12:44
Compare
Choose a tag to compare

1. Gestion des Statistiques et Calcul du Score

a. Score par catégorie et score global

  • Nouveaux champs dans PlayerStats :

    • Ajout de sous-scores pour chaque catégorie :
      • blockScore pour les blocs minés
      • craftScore pour les items craftés
      • mobScore pour les mobs tués
      • timeScore pour le temps de jeu (1 point par minute)
    • Ajout d’un champ totalScore qui est la somme des sous-scores.
  • Méthodes d'incrémentation :

    • Ajout des méthodes addBlockScore(int amount), addCraftScore(int amount), addMobScore(int amount), et addTimeScore(int amount) dans PlayerStats.
    • Lors des événements (bloc cassé, item crafté, mob tué), on récupère la valeur du score depuis la config via ScoreService et on incrémente le sous-score correspondant ET le totalScore.

b. Gestion du temps de jeu

  • Lors de l'insertion d'un snapshot, le temps de jeu actuel (exprimé en minutes via Statistic.PLAY_ONE_MINUTE) est comparé avec le dernier temps enregistré (lastPlayTime).
  • La différence (différence en minutes) est ajoutée au timeScore et au totalScore.
  • Mise à jour du champ lastPlayTime pour assurer la continuité.

2. Chargement de la Configuration

  • ConfigLoader :

    • Lecture du fichier config.yml pour récupérer :
      • Le port à utiliser pour l’API REST (Web.port).
      • Les listes de scores pour les blocs, mobs et crafts (chaque entrée définit un nom et un score).
    • Fournit des méthodes telles que getBlockScore(Material), getMobScore(EntityType) et getCraftScore(Material) qui sont utilisées par le ScoreService pour incrémenter les scores.
  • ScoreService :

    • Une couche intermédiaire qui encapsule l’accès aux scores via le ConfigLoader.
    • Fournit notamment une méthode getTimeScore() renvoyant 1 point par minute.

3. Insertion et Restauration des Snapshots

a. Insertion des snapshots

  • StatsSnapshotService :

    • La méthode insertPlayerSnapshot(...) a été mise à jour pour enregistrer dans le document les maps de statistiques ainsi que les sous-scores (blockScore, craftScore, mobScore, timeScore) et le totalScore.
    • Chaque snapshot inclut également un timestamp (format ISO) pour tracer l'évolution dans le temps.
  • Insertion programmée et à la déconnexion :

    • Une tâche planifiée (toutes les 30 secondes) insère un snapshot pour tous les joueurs connectés.
    • Lors du PlayerQuitEvent, un snapshot est inséré immédiatement pour sauvegarder l'état final des statistiques du joueur.

b. Restauration depuis le dernier snapshot

  • StatsManager.initializePlayerStats(Player) :
    • Lorsqu’un joueur se connecte, la méthode interroge la collection "playerStatsSnapshots" pour récupérer le snapshot le plus récent (trié par timestamp décroissant).
    • Les maps (blocs minés, items craftés, mobs tués) ainsi que les sous-scores (blockScore, craftScore, mobScore, timeScore) et le totalScore sont réinjectés dans l’objet PlayerStats.
    • Ceci permet à l'accumulation des statistiques de reprendre là où elle s'était arrêtée avant redémarrage ou déconnexion.

4. Correction du Comptage lors du Craft

  • Problème des sticks :
    • Lors du craft d’un item comme des sticks, le joueur reçoit un lot (par exemple, 4 sticks) au lieu d’un seul.
  • Solution :
    • Dans l'événement onCraftItem, on récupère le résultat de la recette via event.getRecipe().getResult() et on multiplie la quantité de base par le nombre de fois que le craft est effectué (en cas de shift-click, par exemple).
    • La méthode incrementItemCrafted dans StatsManager a été modifiée pour accepter une quantité en paramètre.

5. API REST et Serveur Web

  • Utilisation de Javalin 6 :

    • Le port utilisé pour démarrer Javalin est désormais chargé depuis le fichier de configuration (config.yml) via configLoader.getWebPort().
    • Javalin est configuré pour servir les fichiers statiques depuis le dossier /web du classpath et exposer les endpoints REST.
  • Endpoints API supplémentaires :

    • Ajout de contrôleurs pour exposer les statistiques, tels que :
      • /api/allstats pour obtenir tous les snapshots.
      • D’autres endpoints pour interroger les statistiques par catégorie (blocs, items, mobs, temps de jeu).

2.1.0

27 Feb 16:07
Compare
Choose a tag to compare

Ce changelog récapitule l'ensemble des modifications récentes apportées au plugin StatCraft pour :

  • Accumuler les statistiques de jeu en mémoire (blocs minés, items craftés, mobs tués).
  • Snapshoter ces statistiques à intervalles réguliers et lors de la déconnexion d'un joueur.
  • Exposer ces données via une API REST (Javalin) et servir une application React.

1. Système de Statistiques en Mémoire

Création du StatsManager & PlayerStats

  • StatsManager :

    • Gestion d'une map en mémoire associant l'UUID du joueur à un objet PlayerStats.
    • Méthodes pour incrémenter les compteurs lors des événements (bloc cassé, item crafté, mob tué).
  • PlayerStats :

    • Stocke trois maps :
      • blocksMined : nombre de blocs minés par type.
      • itemsCrafted : nombre d'items craftés par type.
      • mobsKilled : nombre de mobs tués par type.
    • Ajout de méthodes setBlocksMined(), setItemsCrafted(), et setMobsKilled() pour initialiser les compteurs à partir d'un snapshot (permet de reprendre après redémarrage).

2. Gestion des Événements de Jeu

Événements Utilisés

  • onBlockBreak (BlockBreakEvent)

    • Incrémente le compteur correspondant au type de bloc cassé.
    • Log détaillé de l'événement (ex: "Alex a miné un bloc de STONE").
  • onCraftItem (CraftItemEvent)

    • Incrémente le compteur pour l'item crafté (uniquement lorsque le craft est validé, pas lors de la préparation).
    • Log pour confirmer l'item crafté.
  • onEntityDeath (EntityDeathEvent)

    • Si un joueur tue un mob, incrémente le compteur du type de mob.
    • Log pour indiquer quel type de mob a été tué.
  • onPlayerJoin (PlayerJoinEvent)

    • Vérifie et insère le joueur dans la base Nitrite s'il n'y est pas déjà.
    • Initialise les compteurs en mémoire à partir du dernier snapshot enregistré dans la base, pour garantir la continuité des statistiques.
  • onPlayerQuit (PlayerQuitEvent)

    • Lorsqu'un joueur se déconnecte, un snapshot est immédiatement inséré dans la base pour préserver l'état final des statistiques.
    • Supprime les données en mémoire pour libérer des ressources.

3. Snapshots des Statistiques

Insertion Périodique et à la Déconnexion

  • Snapshots Périodiques

    • Une tâche planifiée (toutes les 30 secondes / 600 ticks) parcourt tous les joueurs connectés.
    • Pour chaque joueur, les compteurs (blocs minés, items craftés, mobs tués) sont lus depuis le StatsManager et combinés avec le temps de jeu (via Statistic.PLAY_ONE_MINUTE).
    • Un snapshot est créé avec un timestamp (format ISO) et inséré dans la collection "playerStatsSnapshots" dans Nitrite.
    • Logs détaillés affichant, pour chaque joueur, le détail par type et le total de chaque catégorie.
  • Insertion lors de la Déconnexion

    • Lors du PlayerQuitEvent, un snapshot est inséré immédiatement pour le joueur concerné.
    • Ceci permet de s'assurer que l'état final des statistiques est sauvegardé, évitant ainsi la réinitialisation à zéro lors d'un redémarrage.

4. API REST et Intégration de l'Application React

API REST avec Javalin

  • Javalin 6 est utilisé pour exposer une API REST et servir les fichiers statiques de l'application React.
  • Endpoints :
    • /api/players : Gère la récupération et l'insertion de données sur les joueurs.
    • /api/allstats : Expose l'ensemble des snapshots de statistiques en JSON.
  • Configuration des Fichiers Statique :
    • Les fichiers issus du build de l'application React sont placés dans le dossier /web du classpath.
    • Javalin est configuré pour servir ces fichiers via le chemin / (ou un autre chemin dédié).

Application React

  • L'application React (buildée avec Create React App) est intégrée dans les ressources du plugin.
  • La configuration du champ "homepage" dans le package.json a été ajustée pour correspondre au chemin de déploiement.
  • L'application communique avec l'API REST pour afficher les statistiques et réaliser des graphiques d'évolution.

5. Persistance et Reprise après Redémarrage

  • Persistance des Snapshots
    • Les snapshots sont stockés de manière persistante dans Nitrite.
  • Reprise des Données en Mémoire
    • Lors de la connexion d'un joueur, le dernier snapshot est récupéré pour initialiser les compteurs dans le StatsManager.
    • Ceci permet que les compteurs ne repartent pas de zéro après un redémarrage, assurant la continuité des statistiques.

2.0.0

21 Feb 14:03
Compare
Choose a tag to compare

Intégration de la base de données Nitrite

  • Mise en place de Nitrite DB :

    • Intégration de Nitrite 4.3.0 pour stocker les données des joueurs.
    • Création de la classe NitriteBuilder qui initialise la base de données avec MVStore.
    • Configuration du fichier de base de données dans le dossier player_statistics/player_statistic.db.
    • Gestion de l'ouverture (openOrCreate("user", "password")) et fermeture de la base via NitriteBuilder.close() lors de l'activation/désactivation du plugin.
  • Gestion du mapping d'entités :

    • Création de la classe PlayerData pour représenter les joueurs.
    • Annotation de PlayerData avec @Entity et @Id provenant de org.dizitart.no2.repository.annotations pour permettre à Nitrite de mapper automatiquement les objets.
    • Résolution d'erreurs de mapping en enregistrant un convertisseur personnalisé.
  • Implémentation d’un EntityConverter personnalisé :

    • Création de la classe PlayerDataConverter implémentant EntityConverter<PlayerData>.
    • Utilisation de Document.createDocument() pour instancier concrètement les documents.
    • Enregistrement du convertisseur via la méthode en chaîne :
      db = Nitrite.builder()
              .loadModule(storeModule)
              .registerEntityConverter(new PlayerDataConverter())
              .openOrCreate("user", "password");
    • Résolution des erreurs "Invalid repository type" et "Can't convert Document to type PlayerData".

Développement de l'API REST avec Javalin

  • Choix de Javalin 6 :

    • Utilisation de Javalin 6 pour créer une API REST intégrée au plugin.
    • Configuration de Javalin pour démarrer sur le port 28700.
  • Configuration des fichiers statiques :

    • Les fichiers statiques (build de l'application React) sont servis depuis le dossier /web (dans les ressources du plugin).
    • Configuration Javalin pour servir ces fichiers statiques sous le chemin /static:
      app = Javalin.create(config -> {
          config.staticFiles.add(staticFileConfig -> {
              staticFileConfig.directory = "/web"; // Dossier dans le classpath
              staticFileConfig.location = Location.CLASSPATH;
              staticFileConfig.hostedPath = "/static"; // Accessible via http://localhost:7000/static
          });
      }).start(27800);
    • Cela permet de dissocier les endpoints de l'API REST (ex. /api/players) du contenu statique.
  • Implémentation des endpoints REST :

    • Création de la classe PlayerController qui expose les endpoints :
      • GET /api/players : renvoie la liste de tous les joueurs enregistrés.
      • POST /api/players : permet d'ajouter un nouveau joueur via un payload JSON.
    • Utilisation de Javalin et de Jackson (intégré dans Javalin) pour gérer la conversion JSON ⇄ objets Java.
    • Exemple d'endpoint dans PlayerController :
      app.get("/api/players", ctx -> {
          List<PlayerData> players = playerService.getAllPlayers();
          ctx.json(players);
      });
    • Création de la classe PlayerService pour encapsuler la logique d'accès à Nitrite.

Intégration de l'application React

  • Développement de l'application React :

    • Création d'une application React avec Create React App.
    • Installation d'Axios pour effectuer les requêtes HTTP vers l'API REST.
    • Conception d'un composant PlayersList qui récupère et affiche la liste des joueurs via une requête GET à l'API (http://localhost:27800/api/players).
  • Build et intégration dans le plugin :

    • Build de l'application React (généralement avec npm run build).
    • Copie du contenu du dossier build dans le dossier /web des ressources du plugin.
    • Mise à jour du champ "homepage" dans le package.json de React pour qu'il corresponde au chemin / (ex. "homepage": "/") afin d'assurer la bonne résolution des chemins relatifs aux ressources (JS, CSS, images).
  • Accès à l'application React via Javalin :

    • L'application React est accessible à l'URL http://localhost:7000/ et se charge automatiquement grâce au fichier index.html placé dans le dossier /web.

Autres améliorations et fonctionnalités

  • Tâche planifiée pour le log des joueurs :

    • Mise en place d'une tâche planifiée (tous les 5 secondes) avec BukkitRunnable pour afficher la liste de tous les joueurs enregistrés dans la console du serveur.
    • Code exemple dans StatCraft.java dans onEnable() :
      new BukkitRunnable() {
          @Override
          public void run() {
              logAllPlayers();
          }
      }.runTaskTimer(this, 0L, 100L);
    • La méthode logAllPlayers() parcourt le repository Nitrite et affiche chaque nom dans la console.
  • Intégration complète dans le plugin Minecraft :

    • Toutes les classes Java (NitriteBuilder, PlayerData, PlayerDataConverter, PlayerService, PlayerController et l'intégration Javalin) sont contenues dans le package me.loutreee.statCraft.
    • L'API REST et le contenu statique (application React) sont servis via Javalin intégré dans le plugin.
    • Le plugin gère à la fois la logique de jeu (ex. lors de la connexion des joueurs) et la persistance des données (via Nitrite DB).

1.2.0

15 Feb 17:13
Compare
Choose a tag to compare

Added

  • Intégration initiale de l'application React :
    • Mise en place d'un front-end React pour l'affichage des données du plugin.
    • Build de l'application React et copie des fichiers statiques dans src/main/resources/web.
    • Configuration de Javalin pour servir les fichiers statiques depuis le dossier web, accessible à la racine de l'URL.
    • L'interface web réagit désormais sur l'URL racine (http://localhost:<port>/index.html), offrant une expérience utilisateur moderne.

Changed

  • Mise à jour de la configuration du serveur Javalin pour intégrer le front-end React sans conflit avec les endpoints existants.

1.0.1

15 Feb 12:51
Compare
Choose a tag to compare

Port Configurable

Mise en place de la possibilité de configurer le port du serveur web via le dossier config.yml :

Web:
  port: 27800

1.0.0

15 Feb 11:50
23e6bd0
Compare
Choose a tag to compare

Amélioration de logs et première release

v5.1.0-beta

14 Feb 23:25
Compare
Choose a tag to compare
v5.1.0-beta Pre-release
Pre-release

Changed

  • Unification des chemins de stockage des statistiques
    • Mise à jour du code pour utiliser un chemin cohérent (player_statistics) à la fois pour l'écriture et la lecture des fichiers XML.
    • Ajout d'un log supplémentaire (System.out.println(...)) permettant de vérifier le chemin absolu utilisé lors de la lecture des données.
    • Retrait de la référence au dossier data/player_statistics, qui causait un problème de lecture (« Aucune donnée trouvée »).

Fixed

  • Lecture des fichiers de statistiques
    • Correction de l'erreur où le plugin ne trouvait pas les sessions et joueurs dans data/player_statistics alors qu'ils étaient écrits dans player_statistics.
    • L'endpoint / de l'interface web Javalin fonctionne désormais correctement et affiche les scores issus des derniers fichiers XML de chaque joueur.

v5.0.0-beta

14 Feb 21:21
Compare
Choose a tag to compare
v5.0.0-beta Pre-release
Pre-release

WEB INTEGRATION !

Added

  • Interface Web avec Javalin :
    • Intégration de Javalin pour fournir une interface web.
    • Ajout des méthodes start() et stop() dans la classe Web pour démarrer et arrêter le serveur web sur le port 7070.
    • Démarrage automatique de Javalin lors de l'activation du plugin via la méthode onEnable() de la classe principale.
  • Logging amélioré :
    • Affichage d'informations de démarrage du serveur Javalin dans les logs.
    • Journalisation détaillée des actions et de la configuration du plugin.
  • Gestion des tâches asynchrones :
    • Mise en place de tâches périodiques pour la journalisation des statistiques des joueurs.

Fixed

  • Dépendances et packaging :
    • Correction de l'erreur NoClassDefFoundError: io/javalin/Javalin en s'assurant que Javalin est bien embarqué dans le jar via le Maven Shade Plugin.
    • Vérification que le jar ombré (shaded jar) est bien utilisé lors du déploiement du plugin.
  • Accès réseau :
    • S'assurer que Javalin écoute sur toutes les interfaces (0.0.0.0) afin de permettre l'accès à l'interface web via l'IP du serveur.

Changed

  • Migration de SparkJava vers Javalin :
    • Remplacement de SparkJava par Javalin pour la gestion de l'interface web, apportant ainsi une meilleure flexibilité et une syntaxe moderne.
  • Configuration du plugin :
    • Mise à jour du pom.xml pour intégrer correctement les dépendances et réduire les conflits lors du packaging.
  • Utilisation des logs :
    • Modification de certains System.out.println pour utiliser le logger du plugin, réduisant ainsi les avertissements liés à l'utilisation de la sortie standard.