Compare commits

...

7 Commits

Author SHA1 Message Date
Ben Woo 86a207fc4d
Merge b4d86ac133 into 278c51d056 2024-03-20 20:55:36 -06:00
Ben Woo 278c51d056
Merge pull request #3056 from Multiverse/zax71MV5/versionCommand
Add `/mv version`
2024-03-12 10:38:12 +08:00
Zax71 caed081f82 Update Ben's name 2024-03-08 18:03:42 +00:00
Zax71 7276da7665 Implement i18n 2024-02-24 13:48:57 +00:00
Zax71 90b8729129 Add Ben and Zax71 to authors 2024-02-24 13:37:23 +00:00
Zax71 c24f198ed0 Add `/mv version` 2024-02-24 13:36:13 +00:00
Ben Woo b4d86ac133
Completely refactor player listener 2023-09-25 15:31:58 +08:00
9 changed files with 209 additions and 209 deletions

View File

@ -0,0 +1,37 @@
package org.mvplugins.multiverse.core.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.MessageType;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.MultiverseCore;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.utils.MVCorei18n;
@Service
@CommandAlias("mv")
class VersionCommand extends MultiverseCommand {
private final MultiverseCore plugin;
@Inject
VersionCommand(@NotNull MVCommandManager commandManager, MultiverseCore plugin) {
super(commandManager);
this.plugin = plugin;
}
@Subcommand("version")
@CommandPermission("multiverse.core.version")
@Description("{@@mv-core.version.description}")
void versionCommand(BukkitCommandIssuer issuer) {
issuer.sendMessage(MessageType.INFO, MVCorei18n.VERSION_MV, "{version}", plugin.getDescription().getVersion());
issuer.sendMessage(MessageType.INFO, MVCorei18n.VERSION_AUTHORS, "{authors}", String.join(", ", plugin.getDescription().getAuthors()));
issuer.sendMessage(MessageType.INFO, MVCorei18n.VERSION_SECRETCODE); // An in joke I don't get...
}
}

View File

@ -188,12 +188,8 @@ public class MVCoreConfig implements MVConfig {
} }
@Override @Override
@Nullable
public String getJoinDestination() { public String getJoinDestination() {
if (Objects.equals(configHandle.get(configNodes.JOIN_DESTINATION), "")) { return configHandle.get(configNodes.JOIN_DESTINATION);
return null;
}
return configHandle.get(configNodes.JOIN_DESTINATION);
} }
@Override @Override

View File

@ -17,7 +17,6 @@ import org.mvplugins.multiverse.core.world.WorldManager;
public class MVChatListener implements InjectableListener { public class MVChatListener implements InjectableListener {
private final MVCoreConfig config; private final MVCoreConfig config;
private final WorldManager worldManager; private final WorldManager worldManager;
private final MVPlayerListener playerListener;
@Inject @Inject
MVChatListener( MVChatListener(
@ -26,7 +25,6 @@ public class MVChatListener implements InjectableListener {
MVPlayerListener playerListener) { MVPlayerListener playerListener) {
this.config = config; this.config = config;
this.worldManager = worldManager; this.worldManager = worldManager;
this.playerListener = playerListener;
} }
/** /**
@ -46,13 +44,7 @@ public class MVChatListener implements InjectableListener {
return; return;
} }
String world = playerListener.getPlayerWorld().get(event.getPlayer().getName()); String prefix = this.worldManager.getLoadedWorld(event.getPlayer().getWorld())
if (world == null) {
world = event.getPlayer().getWorld().getName();
playerListener.getPlayerWorld().put(event.getPlayer().getName(), world);
}
String prefix = this.worldManager.getLoadedWorld(world)
.map(mvworld -> mvworld.isHidden() ? "" : mvworld.getAlias()) .map(mvworld -> mvworld.isHidden() ? "" : mvworld.getAlias())
.getOrElse(""); .getOrElse("");
String chat = event.getFormat(); String chat = event.getFormat();

View File

@ -7,17 +7,15 @@
package org.mvplugins.multiverse.core.listeners; package org.mvplugins.multiverse.core.listeners;
import java.util.Map; import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import com.dumptruckman.minecraft.util.Logging; import com.dumptruckman.minecraft.util.Logging;
import io.vavr.control.Option; import io.vavr.control.Option;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.inject.Provider; import jakarta.inject.Provider;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -37,7 +35,6 @@ import org.mvplugins.multiverse.core.api.BlockSafety;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager; import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.config.MVCoreConfig; import org.mvplugins.multiverse.core.config.MVCoreConfig;
import org.mvplugins.multiverse.core.destination.DestinationsProvider; import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.destination.ParsedDestination;
import org.mvplugins.multiverse.core.economy.MVEconomist; import org.mvplugins.multiverse.core.economy.MVEconomist;
import org.mvplugins.multiverse.core.event.MVRespawnEvent; import org.mvplugins.multiverse.core.event.MVRespawnEvent;
import org.mvplugins.multiverse.core.inject.InjectableListener; import org.mvplugins.multiverse.core.inject.InjectableListener;
@ -45,6 +42,7 @@ import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter;
import org.mvplugins.multiverse.core.teleportation.TeleportQueue; import org.mvplugins.multiverse.core.teleportation.TeleportQueue;
import org.mvplugins.multiverse.core.utils.result.ResultChain; import org.mvplugins.multiverse.core.utils.result.ResultChain;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld; import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.MultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager; import org.mvplugins.multiverse.core.world.WorldManager;
import org.mvplugins.multiverse.core.world.entrycheck.EntryFeeResult; import org.mvplugins.multiverse.core.world.entrycheck.EntryFeeResult;
import org.mvplugins.multiverse.core.world.entrycheck.WorldEntryCheckerProvider; import org.mvplugins.multiverse.core.world.entrycheck.WorldEntryCheckerProvider;
@ -60,7 +58,6 @@ public class MVPlayerListener implements InjectableListener {
private final Provider<WorldManager> worldManagerProvider; private final Provider<WorldManager> worldManagerProvider;
private final BlockSafety blockSafety; private final BlockSafety blockSafety;
private final AsyncSafetyTeleporter safetyTeleporter; private final AsyncSafetyTeleporter safetyTeleporter;
private final Server server;
private final TeleportQueue teleportQueue; private final TeleportQueue teleportQueue;
private final MVEconomist economist; private final MVEconomist economist;
private final WorldEntryCheckerProvider worldEntryCheckerProvider; private final WorldEntryCheckerProvider worldEntryCheckerProvider;
@ -68,8 +65,6 @@ public class MVPlayerListener implements InjectableListener {
private final DestinationsProvider destinationsProvider; private final DestinationsProvider destinationsProvider;
private final EnforcementHandler enforcementHandler; private final EnforcementHandler enforcementHandler;
private final Map<String, String> playerWorld = new ConcurrentHashMap<String, String>();
@Inject @Inject
MVPlayerListener( MVPlayerListener(
MultiverseCore plugin, MultiverseCore plugin,
@ -77,7 +72,6 @@ public class MVPlayerListener implements InjectableListener {
Provider<WorldManager> worldManagerProvider, Provider<WorldManager> worldManagerProvider,
BlockSafety blockSafety, BlockSafety blockSafety,
AsyncSafetyTeleporter safetyTeleporter, AsyncSafetyTeleporter safetyTeleporter,
Server server,
TeleportQueue teleportQueue, TeleportQueue teleportQueue,
MVEconomist economist, MVEconomist economist,
WorldEntryCheckerProvider worldEntryCheckerProvider, WorldEntryCheckerProvider worldEntryCheckerProvider,
@ -89,7 +83,6 @@ public class MVPlayerListener implements InjectableListener {
this.worldManagerProvider = worldManagerProvider; this.worldManagerProvider = worldManagerProvider;
this.blockSafety = blockSafety; this.blockSafety = blockSafety;
this.safetyTeleporter = safetyTeleporter; this.safetyTeleporter = safetyTeleporter;
this.server = server;
this.teleportQueue = teleportQueue; this.teleportQueue = teleportQueue;
this.economist = economist; this.economist = economist;
this.worldEntryCheckerProvider = worldEntryCheckerProvider; this.worldEntryCheckerProvider = worldEntryCheckerProvider;
@ -106,15 +99,6 @@ public class MVPlayerListener implements InjectableListener {
return commandManagerProvider.get(); return commandManagerProvider.get();
} }
/**
* Gets the map of player and the world name they are in.
*
* @return the playerWorld-map
*/
public Map<String, String> getPlayerWorld() {
return playerWorld;
}
/** /**
* This method is called when a player respawns. * This method is called when a player respawns.
* *
@ -122,189 +106,182 @@ public class MVPlayerListener implements InjectableListener {
*/ */
@EventHandler(priority = EventPriority.LOW) @EventHandler(priority = EventPriority.LOW)
public void playerRespawn(PlayerRespawnEvent event) { public void playerRespawn(PlayerRespawnEvent event) {
World world = event.getPlayer().getWorld(); getWorldManager()
LoadedMultiverseWorld mvWorld = getWorldManager().getLoadedWorld(world.getName()).getOrNull(); .getLoadedWorld(event.getPlayer().getWorld())
// If it's not a World MV manages we stop. .filter(mvWorld -> isBedOrAnchorRespawn(event, mvWorld))
if (mvWorld == null) { .flatMap(MultiverseWorld::getRespawnWorld)
return; .map(this::getMostAccurateRespawnLocation)
} .peek(respawnLocation -> callMVRepawnEvent(event, respawnLocation));
if (mvWorld.getBedRespawn() && (event.isBedSpawn() || event.isAnchorSpawn())) {
Logging.fine("Spawning %s at their %s.", event.getPlayer().getName(), event.isBedSpawn() ? "BED" : "ANCHOR");
return;
}
// Get the instance of the World the player should respawn at.
LoadedMultiverseWorld respawnWorld = null;
if (getWorldManager().isLoadedWorld(mvWorld.getRespawnWorld())) {
respawnWorld = getWorldManager().getLoadedWorld(mvWorld.getRespawnWorld()).getOrNull();
}
// If it's null then it either means the World doesn't exist or the value is blank, so we don't handle it.
// NOW: We'll always handle it to get more accurate spawns
if (respawnWorld != null) {
world = respawnWorld.getBukkitWorld().getOrNull();
}
// World has been set to the appropriate world
Location respawnLocation = getMostAccurateRespawnLocation(world);
MVRespawnEvent respawnEvent = new MVRespawnEvent(respawnLocation, event.getPlayer(), "compatability");
this.server.getPluginManager().callEvent(respawnEvent);
event.setRespawnLocation(respawnEvent.getPlayersRespawnLocation());
} }
private Location getMostAccurateRespawnLocation(World w) { private static boolean isBedOrAnchorRespawn(PlayerRespawnEvent event, LoadedMultiverseWorld mvWorld) {
LoadedMultiverseWorld mvw = getWorldManager().getLoadedWorld(w.getName()).getOrNull(); if (mvWorld.getBedRespawn() && (event.isBedSpawn() || event.isAnchorSpawn())) {
if (mvw != null) { Logging.fine("Spawning %s at their %s.",
return mvw.getSpawnLocation(); event.getPlayer().getName(),
event.isBedSpawn() ? "BED" : "ANCHOR");
return false;
} }
return w.getSpawnLocation(); return true;
}
private Location getMostAccurateRespawnLocation(World world) {
return getWorldManager().getLoadedWorld(world.getName())
.map(LoadedMultiverseWorld::getSpawnLocation)
.getOrElse(world.getSpawnLocation());
}
private void callMVRepawnEvent(PlayerRespawnEvent event, Location respawnLocation) {
MVRespawnEvent respawnEvent = new MVRespawnEvent(
respawnLocation, event.getPlayer(), "compatability");
Bukkit.getPluginManager().callEvent(respawnEvent);
event.setRespawnLocation(respawnEvent.getPlayersRespawnLocation());
} }
/** /**
* This method is called when a player joins the server. * This method is called when a player joins the server.
*
* @param event The Event that was fired. * @param event The Event that was fired.
*/ */
@EventHandler @EventHandler
public void playerJoin(PlayerJoinEvent event) { public void playerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
LoadedMultiverseWorld world = getWorldManager().getLoadedWorld(player.getWorld()).getOrNull(); if (player.hasPlayedBefore()) {
if (world == null) { playerJoinAgain(event);
Logging.finer("Player joined in a world that is not managed by Multiverse."); } else {
playerJoinFirstTime(event);
}
// Handle the Players GameMode setting for the new world.
this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld());
}
private void playerJoinAgain(PlayerJoinEvent event) {
Logging.finer("Player joined AGAIN!");
if (!config.getEnableJoinDestination()) {
return;
}
Option.of(destinationsProvider.parseDestination(config.getJoinDestination()))
.peek(joinDestination -> {
Logging.fine("Moving player to: %s", joinDestination);
safetyTeleporter.teleportSafely(event.getPlayer(), joinDestination);
})
.onEmpty(() -> {
Logging.warning("JoinDestination '%s' is invalid! Not teleporting player!",
config.getJoinDestination());
});
}
private void playerJoinFirstTime(PlayerJoinEvent event) {
Logging.finer("Player joined for the FIRST time!");
if (!config.getFirstSpawnOverride()) {
return; return;
} }
Option.of(destinationsProvider.parseDestination(config.getFirstSpawnLocation())) Option.of(destinationsProvider.parseDestination(config.getFirstSpawnLocation()))
.peek(parsedDestination -> { .peek(firstSpawnDestination -> {
if (!player.hasPlayedBefore()) { Logging.fine("Moving NEW player to(firstspawnoverride): %s", firstSpawnDestination);
Logging.finer("Player joined for the FIRST time!"); safetyTeleporter.teleportSafely(event.getPlayer(), firstSpawnDestination);
if (config.getFirstSpawnOverride()) { })
Logging.fine("Moving NEW player to(firstspawnoverride): %s", config.getFirstSpawnLocation()); .onEmpty(() -> {
this.sendPlayerToDefaultWorld(player, parsedDestination); Logging.warning("FirstSpawnLocation '%s' is invalid! Not teleporting player!",
} config.getFirstSpawnLocation());
}
handleJoinDestination(player);
}); });
// Handle the Players GameMode setting for the new world.
this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld());
playerWorld.put(player.getName(), player.getWorld().getName());
}
/**
* Will teleport the player to the destination specified in config
* @param player The {@link Player} to teleport
*/
private void handleJoinDestination(@NotNull Player player) {
if (!config.getEnableJoinDestination()) {
Logging.finer("JoinDestination is disabled");
// User has disabled the feature in config
return;
}
if (config.getJoinDestination() == null) {
Logging.warning("Joindestination is enabled but no destination has been specified in config!");
return;
}
Logging.finer("JoinDestination is " + config.getJoinDestination());
ParsedDestination<?> joinDestination = destinationsProvider.parseDestination(config.getJoinDestination());
if (joinDestination == null) {
Logging.warning("The destination in JoinDestination in config is invalid");
return;
}
// Finally, teleport the player
safetyTeleporter.teleportSafely(player, player, joinDestination);
} }
/** /**
* This method is called when a player changes worlds. * This method is called when a player changes worlds.
*
* @param event The Event that was fired. * @param event The Event that was fired.
*/ */
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void playerChangedWorld(PlayerChangedWorldEvent event) { public void playerChangedWorld(PlayerChangedWorldEvent event) {
// Permissions now determine whether or not to handle a gamemode. // Permissions now determine whether or not to handle a gamemode.
this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld()); handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld());
playerWorld.put(event.getPlayer().getName(), event.getPlayer().getWorld().getName());
} }
/** /**
* This method is called when a player teleports anywhere. * This method is called when a player teleports anywhere.
*
* @param event The Event that was fired. * @param event The Event that was fired.
*/ */
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void playerTeleport(PlayerTeleportEvent event) { public void playerTeleport(PlayerTeleportEvent event) {
Logging.finer("Got teleport event for player '" if (event.getTo() == null) {
+ event.getPlayer().getName() + "' with cause '" + event.getCause() + "'");
if (event.isCancelled()) {
return; return;
} }
Logging.finer("Got teleport event for player '%s' with cause '%s'",
event.getPlayer().getName(), event.getCause());
Player teleportee = event.getPlayer(); Player teleportee = event.getPlayer();
CommandSender teleporter; CommandSender teleporter = getTeleporter(teleportee);
Optional<String> teleporterName = teleportQueue.popFromQueue(teleportee.getName());
if (teleporterName.isPresent()) { World fromWorld = event.getFrom().getWorld();
if (teleporterName.equals("CONSOLE")) { World toWorld = event.getTo().getWorld();
Logging.finer("We know the teleporter is the console! Magical!");
teleporter = this.server.getConsoleSender();
} else {
teleporter = this.server.getPlayerExact(teleporterName.get());
}
} else {
teleporter = teleportee;
}
Logging.finer("Inferred sender '" + teleporter + "' from name '"
+ teleporterName + "', fetched from name '" + teleportee.getName() + "'");
LoadedMultiverseWorld fromWorld = getWorldManager().getLoadedWorld(event.getFrom().getWorld().getName()).getOrNull();
LoadedMultiverseWorld toWorld = getWorldManager().getLoadedWorld(event.getTo().getWorld().getName()).getOrNull();
if (toWorld == null) { if (toWorld == null) {
Logging.fine("Player '" + teleportee.getName() + "' is teleporting to world '" Logging.warning("Player '%s' is teleporting to a world that does not exist. "
+ event.getTo().getWorld().getName() + "' which is not managed by Multiverse-Core. No further " + "No further actions will be taken by Multiverse-Core.", teleportee.getName());
+ "actions will be taken by Multiverse-Core.");
return; return;
} }
if (event.getFrom().getWorld().equals(event.getTo().getWorld())) {
if (Objects.equals(fromWorld, toWorld)) {
// The player is Teleporting to the same world. // The player is Teleporting to the same world.
Logging.finer("Player '" + teleportee.getName() + "' is teleporting to the same world."); Logging.finer("Player '%s' is teleporting to the same world '%s'.",
this.stateSuccess(teleportee.getName(), toWorld.getAlias()); teleportee.getName(), toWorld.getName());
return; return;
} }
ResultChain entryResult = worldEntryCheckerProvider.forSender(teleporter).canEnterWorld(fromWorld, toWorld) checkTeleportEntry(event, toWorld, fromWorld, teleporter, teleportee);
.onSuccessReason(EntryFeeResult.Success.class, reason -> {
if (reason == EntryFeeResult.Success.ENOUGH_MONEY) {
economist.payEntryFee((Player) teleporter, toWorld);
// Send payment receipt
}
})
.onFailure(results -> {
event.setCancelled(true);
getCommandManager().getCommandIssuer(teleporter).sendError(results.getLastResultMessage());
});
Logging.fine("Teleport result: %s", entryResult);
} }
private void stateSuccess(String playerName, String worldName) { private @NotNull CommandSender getTeleporter(Player teleportee) {
Logging.fine("MV-Core is allowing Player '" + playerName return teleportQueue.popFromQueue(teleportee.getName())
+ "' to go to '" + worldName + "'."); .map(teleporterName -> {
Logging.finer("Player '%s' is being teleported by '%s'.",
teleportee.getName(), teleporterName);
return teleporterName.equals("CONSOLE")
? Bukkit.getConsoleSender()
: Bukkit.getPlayerExact(teleporterName);
})
.getOrElse(teleportee);
}
private void checkTeleportEntry(
PlayerTeleportEvent event, World toWorld, World fromWorld, CommandSender teleporter, Player teleportee) {
getWorldManager().getLoadedWorld(toWorld).peek(mvToWorld -> {
LoadedMultiverseWorld mvFromWorld = getWorldManager().getLoadedWorld(fromWorld).getOrNull();
ResultChain entryResult = worldEntryCheckerProvider.forSender(teleporter)
.canEnterWorld(mvFromWorld, mvToWorld)
.onSuccessReason(EntryFeeResult.Success.class, reason -> {
if (teleporter instanceof Player player && reason == EntryFeeResult.Success.ENOUGH_MONEY) {
economist.payEntryFee(player, mvToWorld);
// Send payment receipt
}
})
.onFailure(results -> {
event.setCancelled(true);
getCommandManager().getCommandIssuer(teleporter).sendError(results.getLastResultMessage());
});
Logging.fine("Teleport result: %s", entryResult);
}).onEmpty(() -> {
Logging.fine("Player '%s' is teleporting to world '%s' which is not managed by Multiverse-Core. "
+ "No further actions will be taken by Multiverse-Core.",
teleportee.getName(),
toWorld.getName());
});
} }
/** /**
* This method is called to adjust the portal location to the actual portal location (and not * This method is called to adjust the portal location to the actual portal location (and not
* right outside of it. * right outside of it.
*
* @param event The Event that was fired. * @param event The Event that was fired.
*/ */
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void playerPortalCheck(PlayerPortalEvent event) { public void playerPortalCheck(PlayerPortalEvent event) {
if (event.isCancelled() || event.getFrom() == null) { World fromWorld = event.getFrom().getWorld();
return; if (fromWorld != null && fromWorld.getBlockAt(event.getFrom()).getType() != Material.NETHER_PORTAL) {
}
// REMEMBER! getTo MAY be NULL HERE!!!
// If the player was actually outside of the portal, adjust the from location
if (event.getFrom().getWorld().getBlockAt(event.getFrom()).getType() != Material.NETHER_PORTAL) {
Location newloc = blockSafety.findPortalBlockNextTo(event.getFrom()); Location newloc = blockSafety.findPortalBlockNextTo(event.getFrom());
// TODO: Fix this. Currently, we only check for PORTAL blocks. I'll have to figure out what // TODO: Fix this. Currently, we only check for PORTAL blocks. I'll have to figure out what
// TODO: we want to do here. // TODO: we want to do here.
@ -312,71 +289,56 @@ public class MVPlayerListener implements InjectableListener {
event.setFrom(newloc); event.setFrom(newloc);
} }
} }
// Wait for the adjust, then return!
if (event.getTo() == null) {
return;
}
} }
/** /**
* This method is called when a player actually portals via a vanilla style portal. * This method is called when a player actually portals via a vanilla style portal.
*
* @param event The Event that was fired. * @param event The Event that was fired.
*/ */
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void playerPortal(PlayerPortalEvent event) { public void playerPortal(PlayerPortalEvent event) {
if (event.isCancelled() || (event.getFrom() == null)) {
return;
}
// The adjust should have happened much earlier.
if (event.getTo() == null) { if (event.getTo() == null) {
return; return;
} }
if (config.isUsingCustomPortalSearch()) { if (config.isUsingCustomPortalSearch()) {
event.setSearchRadius(config.getCustomPortalSearchRadius()); event.setSearchRadius(config.getCustomPortalSearchRadius());
} }
LoadedMultiverseWorld fromWorld = getWorldManager().getLoadedWorld(event.getFrom().getWorld().getName()).getOrNull(); if (Objects.equals(event.getFrom().getWorld(), event.getTo().getWorld())) {
LoadedMultiverseWorld toWorld = getWorldManager().getLoadedWorld(event.getTo().getWorld().getName()).getOrNull();
if (event.getFrom().getWorld().equals(event.getTo().getWorld())) {
// The player is Portaling to the same world.
Logging.finer("Player '" + event.getPlayer().getName() + "' is portaling to the same world."); Logging.finer("Player '" + event.getPlayer().getName() + "' is portaling to the same world.");
return; return;
} }
ResultChain entryResult = worldEntryCheckerProvider.forSender(event.getPlayer()).canEnterWorld(fromWorld, toWorld) checkPortalTeleportEntry(event);
.onFailure(results -> {
event.setCancelled(true);
getCommandManager().getCommandIssuer(event.getPlayer()).sendError(results.getLastResultMessage());
});
Logging.fine("Teleport result: %s", entryResult);
} }
private void sendPlayerToDefaultWorld(final Player player, ParsedDestination parsedDestination) { private void checkPortalTeleportEntry(PlayerPortalEvent event) {
// Remove the player 1 tick after the login. I'm sure there's GOT to be a better way to do this... getWorldManager().getLoadedWorld(event.getTo().getWorld()).peek(toWorld -> {
this.server.getScheduler().scheduleSyncDelayedTask(this.plugin, LoadedMultiverseWorld fromWorld = getWorldManager().getLoadedWorld(event.getFrom().getWorld()).getOrNull();
new Runnable() { ResultChain entryResult = worldEntryCheckerProvider.forSender(event.getPlayer())
@Override .canEnterWorld(fromWorld, toWorld)
public void run() { .onFailure(results -> {
safetyTeleporter.teleportSafely(player, player, parsedDestination); event.setCancelled(true);
} getCommandManager().getCommandIssuer(event.getPlayer())
}, 1L); .sendError(results.getLastResultMessage());
});
Logging.fine("Teleport result: %s", entryResult);
});
} }
/** /**
* Handles the gamemode for the specified {@link Player}. * Handles the gamemode for the specified {@link Player} with a 1 tick delay.
* *
* @param player The {@link Player}. * @param player The {@link Player}.
* @param world The {@link World} the player is supposed to be in. * @param world The {@link World} the player is supposed to be in.
*/ */
private void handleGameModeAndFlight(final Player player, World world) { private void handleGameModeAndFlight(final Player player, World world) {
// We perform this task one tick later to MAKE SURE that the player actually reaches the if (!player.isOnline() || !player.getWorld().equals(world)) {
// destination world, otherwise we'd be changing the player mode if they havent moved anywhere. return;
this.server.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> { }
if (!player.isOnline() || !player.getWorld().equals(world)) { enforcementHandler.handleFlightEnforcement(player);
return; enforcementHandler.handleGameModeEnforcement(player);
}
enforcementHandler.handleFlightEnforcement(player);
enforcementHandler.handleGameModeEnforcement(player);
}, 1L);
} }
} }

View File

@ -2,9 +2,9 @@ package org.mvplugins.multiverse.core.teleportation;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import com.dumptruckman.minecraft.util.Logging; import com.dumptruckman.minecraft.util.Logging;
import io.vavr.control.Option;
import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Service;
@Service @Service
@ -29,15 +29,16 @@ public class TeleportQueue {
/** /**
* This method is used to find out who is teleporting a player. * This method is used to find out who is teleporting a player.
*
* @param playerName The teleported player (the teleportee). * @param playerName The teleported player (the teleportee).
* @return The player that teleported the other one (the teleporter). * @return The player that teleported the other one (the teleporter).
*/ */
public Optional<String> popFromQueue(String playerName) { public Option<String> popFromQueue(String playerName) {
if (teleportQueue.containsKey(playerName)) { if (teleportQueue.containsKey(playerName)) {
String teleportee = teleportQueue.get(playerName); String teleportee = teleportQueue.get(playerName);
teleportQueue.remove(playerName); teleportQueue.remove(playerName);
return Optional.of(teleportee); return Option.of(teleportee);
} }
return Optional.empty(); return Option.none();
} }
} }

View File

@ -101,6 +101,11 @@ public enum MVCorei18n implements MessageKeyProvider {
UNLOAD_UNLOADING, UNLOAD_UNLOADING,
UNLOAD_SUCCESS, UNLOAD_SUCCESS,
// version command
VERSION_MV,
VERSION_AUTHORS,
VERSION_SECRETCODE,
// debug command // debug command
DEBUG_INFO_OFF, DEBUG_INFO_OFF,
DEBUG_INFO_ON, DEBUG_INFO_ON,

View File

@ -3,6 +3,7 @@ package org.mvplugins.multiverse.core.world;
import java.util.List; import java.util.List;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import io.vavr.control.Option;
import io.vavr.control.Try; import io.vavr.control.Try;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Difficulty; import org.bukkit.Difficulty;
@ -441,8 +442,8 @@ public class MultiverseWorld {
* *
* @return A world that exists on the server. * @return A world that exists on the server.
*/ */
public @Nullable World getRespawnWorld() { public @Nullable Option<World> getRespawnWorld() {
return Bukkit.getWorld(worldConfig.getRespawnWorld()); return Option.of(Bukkit.getWorld(worldConfig.getRespawnWorld()));
} }
/** /**

View File

@ -139,6 +139,12 @@ mv-core.unload.success=&aWorld '{world}' unloaded!
# /mv usage # /mv usage
mv-core.usage.description=Show Multiverse-Core command usage. mv-core.usage.description=Show Multiverse-Core command usage.
# /mv version
mv-core.version.description=Displays version and authors
mv-core.version.mv=Multiverse Core Version &fv{version}
mv-core.version.authors=Multiverse Core Authors &f{authors}
mv-core.version.secretcode=Special Code: &fFRN002
# commands error # commands error
mv-core.commands.error.playersonly=&cThis command can only be used by players mv-core.commands.error.playersonly=&cThis command can only be used by players
mv-core.commands.error.multiverseworldonly=&cThis can only be used in multiverse worlds mv-core.commands.error.multiverseworldonly=&cThis can only be used in multiverse worlds

View File

@ -1,6 +1,6 @@
name: Multiverse-Core name: Multiverse-Core
main: org.mvplugins.multiverse.core.MultiverseCore main: org.mvplugins.multiverse.core.MultiverseCore
authors: ['dumptruckman', 'Rigby', 'fernferret', 'lithium3141', 'main--'] authors: ['dumptruckman', 'Rigby', 'fernferret', 'lithium3141', 'main--', 'benwoo1110', 'Zax71']
website: 'https://dev.bukkit.org/projects/multiverse-core' website: 'https://dev.bukkit.org/projects/multiverse-core'
softdepend: ['Vault', 'PlaceholderAPI'] softdepend: ['Vault', 'PlaceholderAPI']
api-version: 1.13 api-version: 1.13