diff --git a/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java b/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java index f4f233da..ad16e0b0 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java @@ -36,6 +36,10 @@ import org.jvnet.hk2.annotations.Service; import org.mvplugins.multiverse.external.vavr.control.Try; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + /** * Multiverse-Inventories plugin main class. */ @@ -137,15 +141,19 @@ public final void onEnable() { public void onDisable() { super.onDisable(); + List> futures = new ArrayList<>(); for (final Player player : getServer().getOnlinePlayers()) { SingleShareWriter.of(this, player, Sharables.LAST_LOCATION).write(player.getLocation().clone()); - new WriteOnlyShareHandler(this, player).handleSharing(); + futures.add(new WriteOnlyShareHandler(this, player).handleSharing()); if (inventoriesConfig.get().getApplyPlayerdataOnJoin()) { - profileDataSource.get().modifyGlobalProfile( - GlobalProfileKey.of(player), profile -> profile.setLoadOnLogin(true)); + futures.add(profileDataSource.get() + .modifyGlobalProfile( + GlobalProfileKey.of(player), + profile -> profile.setLoadOnLogin(true) + )); } } - + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); MultiverseInventoriesApi.shutdown(); this.dupingPatch.disable(); this.shutdownDependencyInjection(); diff --git a/src/main/java/org/mvplugins/multiverse/inventories/handleshare/ShareHandler.java b/src/main/java/org/mvplugins/multiverse/inventories/handleshare/ShareHandler.java index e2137649..060e13fe 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/handleshare/ShareHandler.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/handleshare/ShareHandler.java @@ -14,6 +14,8 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import java.util.concurrent.CompletableFuture; + /** * Abstract class for handling sharing of data between worlds and game modes. */ @@ -45,21 +47,22 @@ sealed abstract class ShareHandler permits GameModeShareHandler, ReadOnlyShareHa * Finalizes the transfer from one world to another. This handles the switching * inventories/stats for a player and persisting the changes. */ - public final void handleSharing() { + public CompletableFuture handleSharing() { long startTime = System.nanoTime(); this.prepareProfiles(); ShareHandlingEvent event = this.createEvent(); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { Logging.fine("Share handling has been cancelled by another plugin!"); - return; + return CompletableFuture.completedFuture(null); } logAffectedProfilesCount(); ProfileDataSnapshot snapshot = getSnapshot(); updatePlayer(); - updateProfiles(snapshot); + CompletableFuture future = updateProfiles(snapshot); double timeTaken = (System.nanoTime() - startTime) / 1000000.0; logHandlingComplete(timeTaken, event); + return future; } protected abstract void prepareProfiles(); @@ -89,22 +92,23 @@ private void updatePlayer() { } } - private void updateProfiles(ProfileDataSnapshot snapshot) { + private CompletableFuture updateProfiles(ProfileDataSnapshot snapshot) { if (affectedProfiles.getWriteProfiles().isEmpty()) { Logging.finest("No profiles to write - nothing more to do."); - return; - } - for (PersistingProfile writeProfile : affectedProfiles.getWriteProfiles()) { - updatePersistingProfile(writeProfile, snapshot); + return CompletableFuture.completedFuture(null); } + return CompletableFuture.allOf(affectedProfiles.getWriteProfiles() + .stream() + .map(writeProfile -> updatePersistingProfile(writeProfile, snapshot)) + .toArray(CompletableFuture[]::new)); } - private void updatePersistingProfile(PersistingProfile persistingProfile, ProfileDataSnapshot snapshot) { + private CompletableFuture updatePersistingProfile(PersistingProfile persistingProfile, ProfileDataSnapshot snapshot) { if (persistingProfile.getShares().isEmpty()) { Logging.finest("No shares to write - nothing more to do."); - return; + return CompletableFuture.completedFuture(null); } - profileDataStore.getPlayerProfile(persistingProfile.getProfileKey()) + return profileDataStore.getPlayerProfile(persistingProfile.getProfileKey()) .thenCompose(playerProfile -> { Logging.finer("Persisted: " + persistingProfile.getShares() + " to " + playerProfile.getContainerType() + ":" + playerProfile.getContainerName()