2
2
3
3
import io .javalin .Javalin ;
4
4
import io .javalin .http .staticfiles .Location ;
5
- import org .bukkit .plugin .java .JavaPlugin ;
6
- import org .bukkit .event .Listener ;
5
+ import org .bukkit .Bukkit ;
6
+ import org .bukkit .Material ;
7
+ import org .bukkit .Statistic ;
8
+ import org .bukkit .entity .EntityType ;
9
+ import org .bukkit .entity .Player ;
7
10
import org .bukkit .event .EventHandler ;
11
+ import org .bukkit .event .Listener ;
12
+ import org .bukkit .event .block .BlockBreakEvent ;
13
+ import org .bukkit .event .entity .EntityDeathEvent ;
14
+ import org .bukkit .event .inventory .CraftItemEvent ;
8
15
import org .bukkit .event .player .PlayerJoinEvent ;
9
- import org .bukkit .entity .Player ;
16
+ import org .bukkit .event .player .PlayerQuitEvent ;
17
+ import org .bukkit .plugin .java .JavaPlugin ;
10
18
import org .bukkit .scheduler .BukkitRunnable ;
19
+ import org .dizitart .no2 .collection .Document ;
11
20
import org .dizitart .no2 .filters .FluentFilter ;
12
21
import org .dizitart .no2 .repository .ObjectRepository ;
13
22
14
23
import java .util .List ;
24
+ import java .util .Map ;
15
25
16
26
public final class StatCraft extends JavaPlugin implements Listener {
17
27
18
28
private ObjectRepository <PlayerData > playerRepository ;
19
29
private Javalin app ;
30
+ private StatsManager statsManager ;
20
31
21
32
@ Override
22
33
public void onEnable () {
23
- // Récupère le repository
34
+ // Initialisation du StatsManager pour conserver les stats en mémoire
35
+ statsManager = new StatsManager ();
36
+
37
+ // Récupération du repository Nitrite pour PlayerData
24
38
playerRepository = NitriteBuilder .getPlayerRepository ();
39
+ getServer ().getPluginManager ().registerEvents (this , this );
25
40
26
- // Démarrage de Javalin avec les fichiers statiques (dossier /web dans les ressources)
41
+ // Démarrage de Javalin pour servir l'API REST et les fichiers statiques
27
42
app = Javalin .create (config -> {
28
43
config .staticFiles .add (staticFileConfig -> {
29
- // Pour éviter toute interférence, on peut servir les fichiers statiques dans un chemin dédié
30
44
staticFileConfig .directory = "/web" ; // dossier dans le classpath
31
45
staticFileConfig .location = Location .CLASSPATH ;
32
- staticFileConfig .hostedPath = "/" ; // servir les fichiers statiques sous /static
46
+ staticFileConfig .hostedPath = "/" ;
33
47
});
34
48
}).start (27800 );
35
49
36
- // Instancier le service et le contrôleur pour enregistrer les endpoints
50
+ // Instanciation du service et du contrôleur pour l'API REST
37
51
PlayerService playerService = new PlayerService ();
38
52
new PlayerController (app , playerService );
39
53
54
+ // Enregistrement du contrôleur pour afficher toutes les stats via /api/allstats
55
+ new StatsSnapshotController (app );
56
+
40
57
getLogger ().info ("API REST démarrée sur le port 27800" );
41
58
getLogger ().info ("Plugin StatCraft activé !" );
42
59
43
- // Planifie l'exécution de logAllPlayers() toutes les 5 secondes (100 ticks)
60
+ // Tâche planifiée toutes les 30 secondes (600 ticks) :
61
+ // log et insertion d'un snapshot pour tous les joueurs connectés
44
62
new BukkitRunnable () {
45
63
@ Override
46
64
public void run () {
47
65
logAllPlayers ();
66
+ insertSnapshotsForAllPlayers ();
48
67
}
49
- }.runTaskTimer (this , 0L , 100L );
68
+ }.runTaskTimer (this , 0L , 600L );
50
69
}
51
70
52
71
@ Override
53
72
public void onDisable () {
54
73
if (app != null ) {
55
74
app .stop ();
56
75
}
57
- // Ferme la base
58
76
NitriteBuilder .close ();
59
77
getLogger ().info ("Plugin StatCraft désactivé !" );
60
78
}
61
79
80
+ // --------------------- EVENEMENTS ---------------------
81
+
82
+ // Incrémente le compteur de blocs minés
83
+ @ EventHandler
84
+ public void onBlockBreak (BlockBreakEvent event ) {
85
+ Player player = event .getPlayer ();
86
+ Material blockType = event .getBlock ().getType ();
87
+ statsManager .incrementBlockMined (player , blockType );
88
+ getLogger ().info (player .getName () + " a miné un bloc de " + blockType );
89
+ }
90
+
91
+ // Incrémente le compteur d'items craftés (événement sur craft validé)
92
+ @ EventHandler
93
+ public void onCraftItem (CraftItemEvent event ) {
94
+ if (event .getWhoClicked () instanceof Player player ) {
95
+ if (event .getInventory ().getResult () != null ) {
96
+ Material craftedItem = event .getInventory ().getResult ().getType ();
97
+ statsManager .incrementItemCrafted (player , craftedItem );
98
+ getLogger ().info (player .getName () + " a crafté " + craftedItem );
99
+ }
100
+ }
101
+ }
102
+
103
+ // Incrémente le compteur de mobs tués (si le tueur est un joueur)
104
+ @ EventHandler
105
+ public void onEntityDeath (EntityDeathEvent event ) {
106
+ if (event .getEntity ().getKiller () != null ) {
107
+ Player player = event .getEntity ().getKiller ();
108
+ EntityType mobType = event .getEntityType ();
109
+ statsManager .incrementMobKilled (player , mobType );
110
+ getLogger ().info (player .getName () + " a tué " + mobType );
111
+ }
112
+ }
113
+
114
+ // Lorsqu'un joueur se connecte, on vérifie s'il est déjà dans le repository et on initialise ses stats en mémoire
62
115
@ EventHandler
63
116
public void onPlayerJoin (PlayerJoinEvent event ) {
64
117
Player player = event .getPlayer ();
65
118
String playerName = player .getName ();
66
-
67
- // Vérifie si le joueur est déjà dans la base
68
119
if (playerRepository .find (FluentFilter .where ("name" ).eq (playerName )).toList ().isEmpty ()) {
69
120
PlayerData data = new PlayerData (playerName );
70
121
playerRepository .insert (data );
71
122
getLogger ().info ("Joueur " + playerName + " ajouté à la base de données." );
72
123
} else {
73
124
getLogger ().info ("Joueur " + playerName + " déjà présent dans la base de données." );
74
125
}
126
+ // Initialisation des compteurs en mémoire à partir du dernier snapshot (si existant)
127
+ statsManager .initializePlayerStats (player );
75
128
}
76
129
130
+ // Lorsqu'un joueur se déconnecte, on insère immédiatement un snapshot pour ce joueur
131
+ @ EventHandler
132
+ public void onPlayerQuit (PlayerQuitEvent event ) {
133
+ Player player = event .getPlayer ();
134
+ insertSnapshotForPlayer (player );
135
+ getLogger ().info ("Snapshot inséré lors de la déconnexion de " + player .getName ());
136
+ }
137
+
138
+ // --------------------- METHODES UTILITAIRES ---------------------
139
+
140
+ // Affiche dans la console la liste des joueurs enregistrés dans le repository Nitrite
77
141
public void logAllPlayers () {
78
- // Récupère tous les joueurs depuis le repository
79
142
List <PlayerData > players = NitriteBuilder .getPlayerRepository ().find ().toList ();
80
-
81
143
if (players .isEmpty ()) {
82
144
getLogger ().info ("Aucun joueur n'est enregistré dans la base de données." );
83
145
} else {
@@ -87,4 +149,83 @@ public void logAllPlayers() {
87
149
}
88
150
}
89
151
}
152
+
153
+ // Insère un snapshot pour TOUS les joueurs connectés (utilisé dans la tâche planifiée)
154
+ public void insertSnapshotsForAllPlayers () {
155
+ for (Player player : Bukkit .getOnlinePlayers ()) {
156
+ insertSnapshotForPlayer (player );
157
+ }
158
+ }
159
+
160
+ // Insère un snapshot pour un joueur spécifique
161
+ public void insertSnapshotForPlayer (Player player ) {
162
+ StatsSnapshotService snapshotService = new StatsSnapshotService ();
163
+ String playerId = player .getName ();
164
+ getLogger ().info ("Insertion snapshot pour " + playerId );
165
+
166
+ // Récupération des stats en mémoire pour le joueur
167
+ PlayerStats ps = statsManager .getPlayerStats (player .getUniqueId ());
168
+ if (ps == null ) {
169
+ getLogger ().info (" - Aucune stat en mémoire pour " + playerId );
170
+ return ;
171
+ }
172
+
173
+ // Log des détails pour chaque catégorie
174
+
175
+ // Blocs minés
176
+ Map <String , Integer > blocksMap = ps .getBlocksMined ();
177
+ if (!blocksMap .isEmpty ()) {
178
+ int totalBlocks = 0 ;
179
+ for (String blockType : blocksMap .keySet ()) {
180
+ int count = blocksMap .get (blockType );
181
+ totalBlocks += count ;
182
+ getLogger ().info (" - " + count + " " + blockType + " miné(s)." );
183
+ }
184
+ getLogger ().info (" -> Total blocs minés: " + totalBlocks );
185
+ } else {
186
+ getLogger ().info (" - Aucun bloc miné récupéré." );
187
+ }
188
+
189
+ // Items craftés
190
+ Map <String , Integer > itemsMap = ps .getItemsCrafted ();
191
+ if (!itemsMap .isEmpty ()) {
192
+ int totalItems = 0 ;
193
+ for (String itemType : itemsMap .keySet ()) {
194
+ int count = itemsMap .get (itemType );
195
+ totalItems += count ;
196
+ getLogger ().info (" - " + count + " " + itemType + " crafté(s)." );
197
+ }
198
+ getLogger ().info (" -> Total items craftés: " + totalItems );
199
+ } else {
200
+ getLogger ().info (" - Aucun item crafté récupéré." );
201
+ }
202
+
203
+ // Mobs tués
204
+ Map <String , Integer > mobsMap = ps .getMobsKilled ();
205
+ if (!mobsMap .isEmpty ()) {
206
+ int totalMobs = 0 ;
207
+ for (String mobType : mobsMap .keySet ()) {
208
+ int count = mobsMap .get (mobType );
209
+ totalMobs += count ;
210
+ getLogger ().info (" - " + count + " " + mobType + " tué(s)." );
211
+ }
212
+ getLogger ().info (" -> Total mobs tués: " + totalMobs );
213
+ } else {
214
+ getLogger ().info (" - Aucun mob tué récupéré." );
215
+ }
216
+
217
+ // Temps de jeu (en minutes)
218
+ int playTime = player .getStatistic (Statistic .PLAY_ONE_MINUTE ) / 1200 ;
219
+ getLogger ().info (" - Temps de jeu : " + playTime + " minutes." );
220
+
221
+ // Insertion du snapshot dans la base Nitrite
222
+ snapshotService .insertPlayerSnapshot (
223
+ ps .getPlayerName (),
224
+ ps .getBlocksMined (),
225
+ ps .getItemsCrafted (),
226
+ ps .getMobsKilled (),
227
+ playTime
228
+ );
229
+ getLogger ().info ("Snapshot inséré pour " + playerId );
230
+ }
90
231
}
0 commit comments