diff --git a/build.gradle b/build.gradle index db351654a..1fe0dd6d9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ import org.apache.tools.ant.filters.ReplaceTokens plugins { - id 'org.mvplugins.multiverse-plugin' version '1.2.2' + id 'org.mvplugins.multiverse-plugin' version '1.2.1' } group = 'org.mvplugins.multiverse.core' @@ -25,12 +25,14 @@ repositories { } configure(apiDependencies) { - serverApiVersion = '1.21.8-R0.1-SNAPSHOT' + serverApiVersion = '1.21.9-R0.1-SNAPSHOT' mockBukkitServerApiVersion = '1.21' mockBukkitVersion = '4.78.0' } dependencies { + testImplementation 'io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT' + // Economy externalPlugin('com.github.MilkBowl:VaultAPI:1.7.1') { exclude group: 'org.bukkit', module: 'bukkit' diff --git a/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java b/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java index 8dac371f0..e570a380c 100644 --- a/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java +++ b/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java @@ -23,6 +23,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerPortalEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; @@ -32,16 +33,16 @@ import org.mvplugins.multiverse.core.MultiverseCore; import org.mvplugins.multiverse.core.command.MVCommandManager; import org.mvplugins.multiverse.core.config.CoreConfig; +import org.mvplugins.multiverse.core.destination.DestinationInstance; import org.mvplugins.multiverse.core.destination.DestinationsProvider; -import org.mvplugins.multiverse.core.dynamiclistener.EventRunnable; import org.mvplugins.multiverse.core.dynamiclistener.annotations.DefaultEventPriority; -import org.mvplugins.multiverse.core.dynamiclistener.annotations.EventClass; import org.mvplugins.multiverse.core.dynamiclistener.annotations.EventMethod; import org.mvplugins.multiverse.core.dynamiclistener.annotations.EventPriorityKey; import org.mvplugins.multiverse.core.economy.MVEconomist; import org.mvplugins.multiverse.core.event.MVRespawnEvent; import org.mvplugins.multiverse.core.locale.PluginLocales; import org.mvplugins.multiverse.core.permissions.CorePermissionsChecker; +import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter; import org.mvplugins.multiverse.core.teleportation.BlockSafety; import org.mvplugins.multiverse.core.teleportation.TeleportQueue; import org.mvplugins.multiverse.core.utils.result.ResultChain; @@ -52,7 +53,6 @@ import org.mvplugins.multiverse.core.world.entrycheck.WorldEntryCheckerProvider; import org.mvplugins.multiverse.core.world.helpers.DimensionFinder; import org.mvplugins.multiverse.core.world.helpers.EnforcementHandler; -import org.spigotmc.event.player.PlayerSpawnLocationEvent; /** * Multiverse's Listener for players. @@ -72,6 +72,7 @@ final class MVPlayerListener implements CoreListener { private final EnforcementHandler enforcementHandler; private final DimensionFinder dimensionFinder; private final CorePermissionsChecker corePermissionsChecker; + private final AsyncSafetyTeleporter asyncSafetyTeleporter; private final Map playerWorld = new ConcurrentHashMap<>(); @@ -89,7 +90,8 @@ final class MVPlayerListener implements CoreListener { DestinationsProvider destinationsProvider, EnforcementHandler enforcementHandler, DimensionFinder dimensionFinder, - CorePermissionsChecker corePermissionsChecker) { + CorePermissionsChecker corePermissionsChecker, + AsyncSafetyTeleporter asyncSafetyTeleporter) { this.plugin = plugin; this.config = config; this.worldManagerProvider = worldManagerProvider; @@ -103,6 +105,7 @@ final class MVPlayerListener implements CoreListener { this.enforcementHandler = enforcementHandler; this.dimensionFinder = dimensionFinder; this.corePermissionsChecker = corePermissionsChecker; + this.asyncSafetyTeleporter = asyncSafetyTeleporter; } private WorldManager getWorldManager() { @@ -201,68 +204,63 @@ private Option getMostAccurateRespawnLocation(LoadedMultiverseWorld mv return Option.of(mvWorld.getSpawnLocation()); } - @EventClass("org.spigotmc.event.player.PlayerSpawnLocationEvent") + @EventMethod + // TODO: Consider if this key is needed anymore, need to remove from config.yml as well @EventPriorityKey("mvcore-player-spawn-location") - EventRunnable playerSpawnLocation() { - return new EventRunnable() { - @Override - public void onEvent(PlayerSpawnLocationEvent event) { - Player player = event.getPlayer(); - MultiverseWorld world = getWorldManager().getLoadedWorld(player.getWorld()).getOrNull(); - if (world == null) { - Logging.finer("Player joined in a world that is not managed by Multiverse."); - return; - } - if (!player.hasPlayedBefore()) { - handleFirstSpawn(event); - } else { - handleJoinLocation(event); - } - handleGameModeAndFlight(player, event.getSpawnLocation().getWorld()); - } + void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + if (player.hasPlayedBefore()) { + handleJoinLocation(player); + } else { + handleFirstSpawn(player); + } + handleGameModeAndFlight(player, player.getWorld()); + } - private void handleFirstSpawn(PlayerSpawnLocationEvent event) { - if (!config.getFirstSpawnOverride()) { - Logging.finer("FirstSpawnOverride is disabled"); - // User has disabled the feature in config - return; - } - Logging.fine("Moving NEW player to(firstspawnoverride): %s", config.getFirstSpawnLocation()); - destinationsProvider.parseDestination(config.getFirstSpawnLocation()) - .map(destination -> destination.getLocation(event.getPlayer()) - .peek(event::setSpawnLocation) - .onEmpty(() -> Logging.warning("The destination in FirstSpawnLocation in config is invalid"))) - .onFailure(failure -> { - Logging.warning("Invalid destination in FirstSpawnLocation in config: %s"); - Logging.warning(failure.getFailureMessage().formatted(getLocales())); - }); - } + private void handleFirstSpawn(Player player) { + if (!config.getFirstSpawnOverride()) { + Logging.finer("FirstSpawnOverride is disabled"); + // User has disabled the feature in config + return; + } + Logging.fine("Moving NEW player to(firstspawnoverride): %s", config.getFirstSpawnLocation()); + destinationsProvider.parseDestination(config.getFirstSpawnLocation()) + .peek(destination -> teleportToDestinationOnJoin(player, destination)) + .onFailure(failure -> { + Logging.warning("Invalid destination in FirstSpawnLocation in config: %s"); + Logging.warning(failure.getFailureMessage().formatted(getLocales())); + }); + } - private void handleJoinLocation(PlayerSpawnLocationEvent event) { - if (!config.getEnableJoinDestination()) { - Logging.finer("JoinDestination is disabled"); - // User has disabled the feature in config - return; - } - if (config.getJoinDestination().isBlank()) { - Logging.warning("Joindestination is enabled but no destination has been specified in config!"); - return; - } - if (corePermissionsChecker.hasJoinLocationBypassPermission(event.getPlayer())) { - Logging.finer("Player %s has bypass permission for JoinDestination", event.getPlayer().getName()); - return; - } - Logging.finer("JoinDestination is " + config.getJoinDestination()); - destinationsProvider.parseDestination(config.getJoinDestination()) - .map(destination -> destination.getLocation(event.getPlayer()) - .peek(event::setSpawnLocation) - .onEmpty(() -> Logging.warning("The destination in JoinDestination in config is invalid"))) - .onFailure(failure -> { - Logging.warning("Invalid destination in JoinDestination in config: %s"); - Logging.warning(failure.getFailureMessage().formatted(getLocales())); - }); - } - }; + private void handleJoinLocation(Player player) { + if (!config.getEnableJoinDestination()) { + Logging.finer("JoinDestination is disabled"); + // User has disabled the feature in config + return; + } + if (config.getJoinDestination().isBlank()) { + Logging.warning("Joindestination is enabled but no destination has been specified in config!"); + return; + } + if (corePermissionsChecker.hasJoinLocationBypassPermission(player)) { + Logging.finer("Player %s has bypass permission for JoinDestination", player.getName()); + return; + } + Logging.finer("JoinDestination is " + config.getJoinDestination()); + destinationsProvider.parseDestination(config.getJoinDestination()) + .peek(destination -> teleportToDestinationOnJoin(player, destination)) + .onFailure(failure -> { + Logging.warning("Invalid destination in JoinDestination in config: %s"); + Logging.warning(failure.getFailureMessage().formatted(getLocales())); + }); + } + + private void teleportToDestinationOnJoin(Player player, DestinationInstance destination) { + asyncSafetyTeleporter.to(destination).teleportSingle(player) + .onSuccess(result -> Logging.fine("Player %s has been teleported on join", + player.getName())) + .onFailure(failure -> Logging.warning("Failed to teleport player %s on join: %s", + player.getName(), failure.getFirst())); } /**