5757 *
5858 */
5959public class Store {
60- private static final Material [] MAT = Material .values ();
6160 private static final CharSequence THE_END = "_the_end" ;
6261 private static final CharSequence NETHER = "_nether" ;
6362 private final Database <InventoryStorage > database ;
@@ -198,7 +197,7 @@ private InventoryStorage getInv(Player player) {
198197 * @param world - the world that is associated with these items/elements
199198 */
200199 public void storeInventory (Player player , World world ) {
201- storeAndSave (player , world );
200+ storeAndSave (player , world , false );
202201 clearPlayer (player );
203202 // Done!
204203 }
@@ -207,8 +206,9 @@ public void storeInventory(Player player, World world) {
207206 * Store and save the player to the database
208207 * @param player - player
209208 * @param world - world to save
209+ * @param shutdown - true if this is a shutdown save
210210 */
211- public void storeAndSave (Player player , World world ) {
211+ public void storeAndSave (Player player , World world , boolean shutdown ) {
212212 // Get the player's store
213213 InventoryStorage store = getInv (player );
214214 // Do not differentiate between world environments
@@ -249,57 +249,66 @@ public void storeAndSave(Player player, World world) {
249249 store .setEnderChest (overworldName , contents );
250250 }
251251 if (addon .getSettings ().isStatistics ()) {
252- saveStats (store , player , overworldName ).thenAccept (database ::saveObjectAsync );
252+ saveStats (store , player , overworldName , shutdown ).thenAccept (database ::saveObjectAsync );
253253 return ;
254254 }
255255 database .saveObjectAsync (store );
256256 }
257257
258- private CompletableFuture <InventoryStorage > saveStats (InventoryStorage store , Player player , String worldName ) {
258+ private CompletableFuture <InventoryStorage > saveStats (InventoryStorage store , Player player , String worldName ,
259+ boolean shutdown ) {
259260 CompletableFuture <InventoryStorage > result = new CompletableFuture <>();
260261 store .clearStats (worldName );
262+
261263 // Statistics
262- Bukkit .getScheduler ().runTaskAsynchronously (addon .getPlugin (), () -> {
263- Arrays .stream (Statistic .values ()).forEach (s -> {
264- Map <Material , Integer > map ;
265- Map <EntityType , Integer > entMap ;
266- switch (s .getType ()) {
267- case BLOCK -> {
268- map = Arrays .stream (MAT ).filter (Material ::isBlock ).filter (m -> !m .isLegacy ())
269- .filter (m -> player .getStatistic (s , m ) > 0 )
270- .collect (Collectors .toMap (k -> k , v -> player .getStatistic (s , v )));
271- if (!map .isEmpty ()) {
272- store .getBlockStats (worldName ).put (s , map );
273- }
274- }
275- case ITEM -> {
276- map = Arrays .stream (MAT ).filter (Material ::isItem ).filter (m -> !m .isLegacy ())
277- .filter (m -> player .getStatistic (s , m ) > 0 )
278- .collect (Collectors .toMap (k -> k , v -> player .getStatistic (s , v )));
279- if (!map .isEmpty ()) {
280- store .getItemStats (worldName ).put (s , map );
281- }
264+ if (shutdown ) {
265+ saveStatistics (result , store , player , worldName );
266+ } else {
267+ // Cannot schedule tasks on shutdown
268+ Bukkit .getScheduler ().runTaskAsynchronously (addon .getPlugin (),
269+ () -> saveStatistics (result , store , player , worldName ));
270+ }
271+ return result ;
272+
273+ }
274+
275+ private void saveStatistics (CompletableFuture <InventoryStorage > result , InventoryStorage store , Player player ,
276+ String worldName ) {
277+ Arrays .stream (Statistic .values ()).forEach (s -> {
278+ Map <Material , Integer > map ;
279+ Map <EntityType , Integer > entMap ;
280+ switch (s .getType ()) {
281+ case BLOCK -> {
282+ map = InvSwitcher .MAT .stream ().filter (Material ::isBlock ).filter (m -> player .getStatistic (s , m ) > 0 )
283+ .collect (Collectors .toMap (k -> k , v -> player .getStatistic (s , v )));
284+ if (!map .isEmpty ()) {
285+ store .getBlockStats (worldName ).put (s , map );
282286 }
283- case ENTITY -> {
284- entMap = Arrays .stream (EntityType .values ()).filter (EntityType ::isAlive )
285- .filter (m -> player .getStatistic (s , m ) > 0 )
286- .collect (Collectors .toMap (k -> k , v -> player .getStatistic (s , v )));
287- if (!entMap .isEmpty ()) {
288- store .getEntityStats (worldName ).put (s , entMap );
289- }
287+ }
288+ case ITEM -> {
289+ map = InvSwitcher .MAT .stream ().filter (Material ::isItem ).filter (m -> player .getStatistic (s , m ) > 0 )
290+ .collect (Collectors .toMap (k -> k , v -> player .getStatistic (s , v )));
291+ if (!map .isEmpty ()) {
292+ store .getItemStats (worldName ).put (s , map );
290293 }
291- case UNTYPED -> {
292- int sc = player .getStatistic (s );
293- if (sc > 0 ) {
294- store .getUntypedStats (worldName ).put (s , sc );
295- }
294+ }
295+ case ENTITY -> {
296+ entMap = Arrays .stream (EntityType .values ()).filter (EntityType ::isAlive )
297+ .filter (m -> player .getStatistic (s , m ) > 0 )
298+ .collect (Collectors .toMap (k -> k , v -> player .getStatistic (s , v )));
299+ if (!entMap .isEmpty ()) {
300+ store .getEntityStats (worldName ).put (s , entMap );
296301 }
302+ }
303+ case UNTYPED -> {
304+ int sc = player .getStatistic (s );
305+ if (sc > 0 ) {
306+ store .getUntypedStats (worldName ).put (s , sc );
297307 }
298- });
299- result . complete ( store );
308+ }
309+ }
300310 });
301- return result ;
302-
311+ result .complete (store );
303312 }
304313
305314 /**
@@ -461,7 +470,7 @@ private static void setTotalExperience(final Player player, final int exp)
461470 /**
462471 * Save all online players
463472 */
464- public void saveOnlinePlayers () {
465- Bukkit .getOnlinePlayers ().forEach (p -> this .storeAndSave (p , p .getWorld ()));
473+ public void saveOnShutdown () {
474+ Bukkit .getOnlinePlayers ().forEach (p -> this .storeAndSave (p , p .getWorld (), true ));
466475 }
467476}
0 commit comments