From 05c5cd8d66054e148bb60f6c41b3e060ebb234a6 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Fri, 10 Feb 2023 15:43:28 +0800 Subject: [PATCH] feat!: Revamp permission handling and its relevant checks --- .../MultiverseCore/MultiverseCore.java | 24 +- .../MultiverseCore/api/MVCore.java | 15 +- .../MultiverseCore/api/MVDestination.java | 142 ------ .../MultiverseCore/api/MVWorld.java | 29 -- .../MultiverseCore/commands/CheckCommand.java | 7 +- .../commands/TeleportCommand.java | 6 +- .../destination/DestinationsProvider.java | 76 +--- .../MultiverseCore/economy/MVEconomist.java | 28 ++ .../MultiverseCore/event/MVTeleportEvent.java | 14 +- .../listeners/MVPlayerListener.java | 339 ++++++++------- .../utils/ActionCheckResult.java | 56 +++ .../MultiverseCore/utils/MVPermissions.java | 405 ------------------ .../MultiverseCore/utils/PermissionTools.java | 302 ------------- .../MultiverseCore/utils/PermissionsTool.java | 225 ++++++++++ .../utils/PlayerActionChecker.java | 181 ++++++++ .../utils/action/ActionResponse.java | 64 +++ .../utils/action/ActionResult.java | 9 + .../MultiverseCore/world/SimpleMVWorld.java | 90 +--- .../world/SimpleMVWorldManager.java | 20 +- .../world/configuration/EntryFee.java | 2 +- 20 files changed, 782 insertions(+), 1252 deletions(-) delete mode 100644 src/main/java/com/onarandombox/MultiverseCore/api/MVDestination.java create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/ActionCheckResult.java delete mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/MVPermissions.java delete mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/PermissionTools.java create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/PermissionsTool.java create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/PlayerActionChecker.java create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/action/ActionResponse.java create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/action/ActionResult.java diff --git a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java index a9e3c2b1..f731d28a 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java @@ -62,7 +62,8 @@ import com.onarandombox.MultiverseCore.listeners.MVWorldListener; import com.onarandombox.MultiverseCore.teleportation.SimpleBlockSafety; import com.onarandombox.MultiverseCore.teleportation.SimpleLocationManipulation; import com.onarandombox.MultiverseCore.teleportation.SimpleSafeTTeleporter; -import com.onarandombox.MultiverseCore.utils.MVPermissions; +import com.onarandombox.MultiverseCore.utils.PermissionsTool; +import com.onarandombox.MultiverseCore.utils.PlayerActionChecker; import com.onarandombox.MultiverseCore.utils.TestingMode; import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper; import com.onarandombox.MultiverseCore.utils.metrics.MetricsConfigurator; @@ -90,7 +91,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore { private DestinationsProvider destinationsProvider; private MVEconomist economist; private LocationManipulation locationManipulation = new SimpleLocationManipulation(); - private final MVPermissions mvPermissions = new MVPermissions(this); + private final PermissionsTool permissionsTool = new PermissionsTool(this); + private PlayerActionChecker playerActionChecker; private SafeTTeleporter safeTTeleporter = new SimpleSafeTTeleporter(this); private final UnsafeCallWrapper unsafeCallWrapper = new UnsafeCallWrapper(this); private final MVWorldManager worldManager = new SimpleMVWorldManager(this); @@ -102,7 +104,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore { // Listeners private MVChatListener chatListener; private final MVEntityListener entityListener = new MVEntityListener(this); - private final MVPlayerListener playerListener = new MVPlayerListener(this); + private MVPlayerListener playerListener; private final MVPortalListener portalListener = new MVPortalListener(this); private final MVWeatherListener weatherListener = new MVWeatherListener(this); private final MVWorldListener worldListener = new MVWorldListener(this); @@ -137,6 +139,9 @@ public class MultiverseCore extends JavaPlugin implements MVCore { */ @Override public void onEnable() { + this.permissionsTool.setUpPermissions(); + this.playerActionChecker = new PlayerActionChecker(this); + // Load our configs first as we need them for everything else. this.loadConfigs(); if (this.multiverseConfig == null) { @@ -186,6 +191,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore { */ private void registerEvents() { PluginManager pluginManager = getServer().getPluginManager(); + this.playerListener = new MVPlayerListener(this); this.chatListener = new MVChatListener(this, this.playerListener); pluginManager.registerEvents(this.chatListener, this); pluginManager.registerEvents(this.entityListener, this); @@ -274,12 +280,14 @@ public class MultiverseCore extends JavaPlugin implements MVCore { return economist; } - /** - * {@inheritDoc} - */ @Override - public MVPermissions getMVPerms() { - return this.mvPermissions; + public PermissionsTool getPermissionsTool() { + return permissionsTool; + } + + @Override + public PlayerActionChecker getPlayerActionChecker() { + return playerActionChecker; } /** diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVCore.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVCore.java index 2f1a8c62..b3429ca7 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/MVCore.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MVCore.java @@ -14,7 +14,8 @@ import com.onarandombox.MultiverseCore.economy.MVEconomist; import com.onarandombox.MultiverseCore.teleportation.SimpleBlockSafety; import com.onarandombox.MultiverseCore.teleportation.SimpleLocationManipulation; import com.onarandombox.MultiverseCore.teleportation.SimpleSafeTTeleporter; -import com.onarandombox.MultiverseCore.utils.MVPermissions; +import com.onarandombox.MultiverseCore.utils.PermissionsTool; +import com.onarandombox.MultiverseCore.utils.PlayerActionChecker; import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper; /** @@ -44,14 +45,6 @@ public interface MVCore extends MVPlugin { */ UnsafeCallWrapper getUnsafeCallWrapper(); - /** - * Multiverse uses an advanced permissions setup, this object - * simplifies getting/setting permissions. - * - * @return A non-null {@link MVPermissions}. - */ - MVPermissions getMVPerms(); - /** * Multiverse uses {@link MVCommandManager} to make adding and using commands * a piece of cake. @@ -113,6 +106,10 @@ public interface MVCore extends MVPlugin { */ int getPluginCount(); + PermissionsTool getPermissionsTool(); + + PlayerActionChecker getPlayerActionChecker(); + /** * Gets the {@link BlockSafety} this {@link MVCore} is using. * @return The {@link BlockSafety} this {@link MVCore} is using. diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVDestination.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVDestination.java deleted file mode 100644 index 6cafabb4..00000000 --- a/src/main/java/com/onarandombox/MultiverseCore/api/MVDestination.java +++ /dev/null @@ -1,142 +0,0 @@ -/****************************************************************************** - * Multiverse 2 Copyright (c) the Multiverse Team 2011. * - * Multiverse 2 is licensed under the BSD License. * - * For more information please check the README.md file included * - * with this project. * - ******************************************************************************/ - -package com.onarandombox.MultiverseCore.api; - -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.util.Vector; - -/** - * A destination API for Multiverse - * Any plugin can add these to MV and when they are, any action that uses them (portals, MVTP, etc.) can use them! - */ -@Deprecated -public interface MVDestination { - /** - * Returns the identifier or prefix that is required for this destination. - *

- * Portals have a prefix of "p" for example and OpenWarp (third party plugin) uses "ow". This is derived from a - * hash and cannot have duplicate values. Read that as your plugin cannot use 'p' because it's already used. - * Please check the wiki when adding a custom destination! - * - * @return The identifier or prefix that is required for this destination. - */ - String getIdentifier(); - - /** - * Allows you to determine if a Destination is valid for the type it thinks it is. - *

- * An example of this would be the exact destination. A valid string would be: e:0,0,0 where an invalid one would - * be e:1:2:3. The first string would return true the second would return false. This is simply a convenience - * method - * and does not even NEED to be called, but it's highly recommended if you're teleporting, but it's mainly for - * Multiverse Internal use. - * - * @param plugin The plugin who the type belongs to. - * @param destination The destination string. ex: p:MyPortal:nw - * - * @return True if the destination is valid, false if not. - */ - boolean isThisType(JavaPlugin plugin, String destination); - - /** - * Returns the location a specific entity will spawn at when being teleported to this Destination. - *

- * To just retrieve the location as it is stored you can just pass null, but be warned some destinations may return - * null back to you if you do this. It is always safer to pass an actual entity. This is used so things like - * minecarts can be teleported. - *

- * Do not forget to use {@link #getVelocity()} as destinations can use this too! - * - * @param entity The entity to be teleported. - * - * @return The location of the entity. - */ - Location getLocation(Entity entity); - - /** - * Returns the velocity vector for this destination. - *

- * Plugins wishing to fully support MVDestinations MUST implement this. - * - * @return A vector representing the speed/direction the player should travel when arriving - */ - Vector getVelocity(); - - /** - * Sets the destination string. - *

- * This should be used when you want to tell this destination object about a change in where it should take people. - * The destination param should be match the result from {@link #getIdentifier()}. A valid example would be that if - * {@link #getIdentifier()} returned "ow" our destination string could be "ow:TownCenter" but could not be - * "p:HomePortal" - * - * @param plugin The plugin who the type belongs to. - * @param destination The destination string. ex: p:MyPortal:nw - */ - void setDestination(JavaPlugin plugin, String destination); - - /** - * Returns true if the destination is valid and players will be taken to it. - *

- * Even if destinations are in the correct format (p:MyPortal) MyPortal may not exist, and therefore this would - * return false. - * - * @return True if the destination is valid; false if not. - */ - boolean isValid(); - - /** - * Gives you a general friendly description of the type of destination. - *

- * For example, the PlayerDestination sets this to "Player". You can use this to show where a player will be taken. - * - * @return A friendly string description of the type of destination. - */ - String getType(); - - /** - * Gives you a specific name of the destination. - *

- * For example, the PlayerDestination sets this to The Player's Name. - * - * @return A friendly string stating the name of the destination. - */ - String getName(); - - /** - * Returns a string that can easily be saved in the config that contains all the details needed to rebuild this - * destination. - *

- * ex: e:0,0,0:50:50 - * - * @return The savable config string. - */ - String toString(); - - /** - * Returns the permissions string required to go here. - *

- * ex: multiverse.access.world - *

- * NOTE: This is NOT the permission to use the teleport command. - * - * @return the permissions string required to go here. - */ - String getRequiredPermission(); - - /** - * Should the Multiverse SafeTeleporter be used? - *

- * If not, MV will blindly take people to the location specified. - * - * @return True if the SafeTeleporter will be used, false if not. - */ - boolean useSafeTeleporter(); -} diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorld.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorld.java index 0ddcd7ba..c91eddb2 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorld.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorld.java @@ -20,7 +20,6 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.WorldType; -import org.bukkit.permissions.Permission; import org.jetbrains.annotations.Nullable; /** @@ -200,34 +199,6 @@ public interface MVWorld { boolean clearList(String property); // end of old config stuff - // permission stuff - /** - * Gets the lowercased name of the world. This method is required, since the permissables - * lowercase all permissions when recalculating. - *

- * Note: This also means if a user has worlds named: world and WORLD, that they can both - * exist, and both be teleported to independently, but their permissions **cannot** be - * uniqueified at this time. See bug report #. - * - * @return The lowercased name of the world. - */ - String getPermissibleName(); - - /** - * Gets the permission required to enter this world. - * - * @return The permission required to be exempt from charges to/from this world. - */ - Permission getAccessPermission(); - - /** - * Gets the permission required to be exempt when entering. - * - * @return The permission required to be exempt when entering. - */ - Permission getExemptPermission(); - // end of permission stuff - /** * Gets the alias of this world. *

diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CheckCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CheckCommand.java index 99ebb735..5c95252f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CheckCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CheckCommand.java @@ -35,6 +35,11 @@ public class CheckCommand extends MultiverseCoreCommand { ) { issuer.sendMessage("Checking " + player + " to " + destination + "..."); //TODO More detailed output on permissions required. - this.plugin.getDestinationsProvider().checkTeleportPermissions(issuer, player, destination); + if (!this.plugin.getPlayerActionChecker().canUseDestinationToTeleport(issuer.getIssuer(), player, destination).isSuccessful()) { + issuer.sendMessage("You don't have permission to use this destination."); + } + if (!this.plugin.getPlayerActionChecker().canGoToDestination(issuer.getIssuer(), player, destination).isSuccessful()) { + issuer.sendMessage("You don't have permission to teleport to this destination."); + } } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java index 78e507f5..14cdef1e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java @@ -35,6 +35,10 @@ public class TeleportCommand extends MultiverseCoreCommand { ) { // TODO Add warning if teleporting too many players at once. for (Player player : players) { + if (!this.plugin.getPlayerActionChecker().canUseDestinationToTeleport(issuer.getIssuer(), player, destination).isSuccessful()) { + issuer.sendMessage("You don't have permission to use this destination."); + continue; + } issuer.sendMessage("Teleporting " + (issuer.getPlayer() == player ? "you" : player.getName()) + " to " + destination + "..."); @@ -44,6 +48,6 @@ public class TeleportCommand extends MultiverseCoreCommand { @Override public boolean hasPermission(CommandIssuer issuer) { - return this.plugin.getDestinationsProvider().hasAnyTeleportPermission(issuer); + return this.plugin.getPermissionsTool().hasAnyDestinationTeleportPermissions(issuer.getIssuer()); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/destination/DestinationsProvider.java b/src/main/java/com/onarandombox/MultiverseCore/destination/DestinationsProvider.java index 6e4d3b2b..1ba28405 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/destination/DestinationsProvider.java +++ b/src/main/java/com/onarandombox/MultiverseCore/destination/DestinationsProvider.java @@ -6,15 +6,12 @@ import java.util.Map; import java.util.stream.Collectors; import co.aikar.commands.BukkitCommandIssuer; -import co.aikar.commands.CommandIssuer; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.Destination; import com.onarandombox.MultiverseCore.api.DestinationInstance; import com.onarandombox.MultiverseCore.api.Teleporter; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; -import org.bukkit.permissions.Permission; -import org.bukkit.plugin.PluginManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,7 +20,6 @@ import org.jetbrains.annotations.Nullable; */ public class DestinationsProvider { private static final String SEPARATOR = ":"; - private static final String PERMISSION_PREFIX = "multiverse.teleport."; private final MultiverseCore plugin; private final Map> destinationMap; @@ -45,13 +41,7 @@ public class DestinationsProvider { */ public void registerDestination(@NotNull Destination destination) { this.destinationMap.put(destination.getIdentifier(), destination); - this.registerDestinationPerms(destination); - } - - private void registerDestinationPerms(@NotNull Destination destination) { - PluginManager pluginManager = this.plugin.getServer().getPluginManager(); - pluginManager.addPermission(new Permission(PERMISSION_PREFIX + "self." + destination.getIdentifier())); - pluginManager.addPermission(new Permission(PERMISSION_PREFIX + "other." + destination.getIdentifier())); + this.plugin.getPermissionsTool().registerDestinationTeleportPermissions(destination); } /** @@ -65,8 +55,8 @@ public class DestinationsProvider { @Nullable String deststring ) { return destinationMap.values().stream() - .filter(destination -> issuer.hasPermission(PERMISSION_PREFIX + "self." + destination.getIdentifier()) - || issuer.hasPermission(PERMISSION_PREFIX + "other." + destination.getIdentifier())) + .filter(destination -> this.plugin.getPermissionsTool().hasDestinationTeleportPermission(null, issuer.getIssuer(), destination) + || this.plugin.getPermissionsTool().hasDestinationTeleportPermission(issuer.getIssuer(), this.plugin.getServer().getConsoleSender(), destination)) .map(destination -> destination.suggestDestinations(issuer, deststring).stream() .map(s -> destination.getIdentifier() + SEPARATOR + s) .collect(Collectors.toList())) @@ -118,6 +108,10 @@ public class DestinationsProvider { return this.destinationMap.get(identifier); } + public @NotNull Collection> getRegisteredDestinations() { + return this.destinationMap.values(); + } + /** * Teleports the teleportee to the destination. * @@ -129,9 +123,6 @@ public class DestinationsProvider { @NotNull Player teleportee, @NotNull ParsedDestination destination ) { - if (!checkTeleportPermissions(teleporter, teleportee, destination)) { - return; - } teleport(teleporter, teleportee, destination); } @@ -152,57 +143,4 @@ public class DestinationsProvider { } teleportHandler.teleport(teleporter, teleportee, destination); } - - /** - * Checks if the teleporter has permission to teleport the teleportee to the destination. - * - * @param teleporter The teleporter. - * @param teleportee The teleportee. - * @param destination The destination. - * @return True if the teleporter has permission, false otherwise. - */ - public boolean checkTeleportPermissions(CommandIssuer teleporter, Entity teleportee, ParsedDestination destination) { - //TODO Move permission checking to a separate class - String permission = PERMISSION_PREFIX - + (teleportee.equals(teleporter.getIssuer()) ? "self" : "other") + "." - + destination.getDestination().getIdentifier(); - if (!teleporter.hasPermission(permission)) { - teleporter.sendMessage("You don't have permission to teleport to this destination."); - return false; - } - - //TODO Config whether to use finer permission - String finerPermissionSuffix = destination.getDestinationInstance().getFinerPermissionSuffix(); - if (finerPermissionSuffix == null || finerPermissionSuffix.isEmpty()) { - return true; - } - - String finerPermission = permission + "." + finerPermissionSuffix; - if (!teleporter.hasPermission(finerPermission)) { - teleporter.sendMessage("You don't have permission to teleport to this destination."); - return false; - } - - return true; - } - - /** - * Checks if the issuer has permission to teleport to at least one destination. - * - * @param issuer The issuer. - * @return True if the issuer has permission, false otherwise. - */ - public boolean hasAnyTeleportPermission(CommandIssuer issuer) { - for (Destination destination : this.destinationMap.values()) { - String permission = PERMISSION_PREFIX + "self." + destination.getIdentifier(); - if (issuer.hasPermission(permission)) { - return true; - } - permission = PERMISSION_PREFIX + "other." + destination.getIdentifier(); - if (issuer.hasPermission(permission)) { - return true; - } - } - return false; - } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/economy/MVEconomist.java b/src/main/java/com/onarandombox/MultiverseCore/economy/MVEconomist.java index 82dcf9fd..8b10c94d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/economy/MVEconomist.java +++ b/src/main/java/com/onarandombox/MultiverseCore/economy/MVEconomist.java @@ -1,5 +1,6 @@ package com.onarandombox.MultiverseCore.economy; +import com.onarandombox.MultiverseCore.api.MVWorld; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.entity.Player; @@ -30,6 +31,10 @@ public class MVEconomist { return getVaultHandler().hasEconomy(); } + public String formatPrice(MVWorld world) { + return formatPrice(world.getPrice(), world.getCurrency()); + } + /** * Formats the amount to a human readable currency string. * @@ -76,6 +81,29 @@ public class MVEconomist { } } + public void payEntryFee(Player player, MVWorld world) { + payEntryFee(player, world.getPrice(), world.getCurrency()); + } + + /** + * Pays for a given amount of currency either from the player's economy account or inventory if the currency + * + * @param player the player to take currency from. + * @param price the amount to take. + * @param currency the type of currency. + */ + public void payEntryFee(Player player, double price, Material currency) { + if (price == 0D) { + return; + } + + if (price < 0) { + this.deposit(player, -price, currency); + } else { + this.withdraw(player, price, currency); + } + } + /** * Formats a message for a player indicating they don't have enough currency. * diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java index 75afb3dd..cafc5916 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVTeleportEvent.java @@ -7,8 +7,8 @@ package com.onarandombox.MultiverseCore.event; -import com.onarandombox.MultiverseCore.api.MVDestination; import com.onarandombox.MultiverseCore.api.SafeTTeleporter; +import com.onarandombox.MultiverseCore.destination.ParsedDestination; import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -20,13 +20,13 @@ import org.bukkit.event.HandlerList; * Event that gets called when a player use the /mvtp command. */ public class MVTeleportEvent extends Event implements Cancellable { - private Player teleportee; - private CommandSender teleporter; - private MVDestination dest; - private boolean useSafeTeleport; + private final Player teleportee; + private final CommandSender teleporter; + private final ParsedDestination dest; + private final boolean useSafeTeleport; private boolean isCancelled; - public MVTeleportEvent(MVDestination dest, Player teleportee, CommandSender teleporter, boolean safeTeleport) { + public MVTeleportEvent(ParsedDestination dest, Player teleportee, CommandSender teleporter, boolean safeTeleport) { this.teleportee = teleportee; this.teleporter = teleporter; this.dest = dest; @@ -83,7 +83,7 @@ public class MVTeleportEvent extends Event implements Cancellable { * * @return The destination the player will spawn at. */ - public MVDestination getDestination() { + public ParsedDestination getDestination() { return this.dest; } diff --git a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java index 3bd1f2ae..f2774c05 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java +++ b/src/main/java/com/onarandombox/MultiverseCore/listeners/MVPlayerListener.java @@ -8,14 +8,19 @@ package com.onarandombox.MultiverseCore.listeners; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; +import co.aikar.commands.BukkitCommandIssuer; import com.dumptruckman.minecraft.util.Logging; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.event.MVRespawnEvent; -import com.onarandombox.MultiverseCore.utils.PermissionTools; +import com.onarandombox.MultiverseCore.utils.action.ActionResponse; +import com.onarandombox.MultiverseCore.utils.ActionCheckResult; +import com.onarandombox.MultiverseCore.utils.PlayerActionChecker; +import com.onarandombox.MultiverseCore.utils.action.ActionResult; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -30,6 +35,8 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerPortalEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Multiverse's {@link Listener} for players. @@ -37,19 +44,20 @@ import org.bukkit.event.player.PlayerTeleportEvent; public class MVPlayerListener implements Listener { private final MultiverseCore plugin; private final MVWorldManager worldManager; - private final PermissionTools pt; + private final PlayerActionChecker actionChecker; - private final Map playerWorld = new ConcurrentHashMap(); + private final Map playerWorld = new ConcurrentHashMap<>(); public MVPlayerListener(MultiverseCore plugin) { this.plugin = plugin; worldManager = plugin.getMVWorldManager(); - pt = new PermissionTools(plugin); + actionChecker = plugin.getPlayerActionChecker(); } /** * @return the playerWorld-map */ + @Deprecated public Map getPlayerWorld() { return playerWorld; } @@ -105,26 +113,32 @@ public class MVPlayerListener implements Listener { */ @EventHandler public void playerJoin(PlayerJoinEvent event) { - Player p = event.getPlayer(); - if (!p.hasPlayedBefore()) { + Player player = event.getPlayer(); + if (!player.hasPlayedBefore()) { Logging.finer("Player joined for the FIRST time!"); - if (plugin.getMVConfig().getFirstSpawnOverride()) { - Logging.fine("Moving NEW player to(firstspawnoverride): " - + worldManager.getFirstSpawnWorld().getSpawnLocation()); - this.sendPlayerToDefaultWorld(p); + if (!plugin.getMVConfig().getFirstSpawnOverride()) { + return; } + Logging.fine("Moving NEW player to(firstspawnoverride): " + worldManager.getFirstSpawnWorld().getSpawnLocation()); + this.sendPlayerToDefaultWorld(player); return; - } else { - Logging.finer("Player joined AGAIN!"); - if (this.plugin.getMVConfig().getEnforceAccess() // check this only if we're enforcing access! - && !this.plugin.getMVPerms().hasPermission(p, "multiverse.access." + p.getWorld().getName(), false)) { - p.sendMessage("[MV] - Sorry you can't be in this world anymore!"); - this.sendPlayerToDefaultWorld(p); - } } + + Logging.finer("Player joined AGAIN!"); + MVWorld world = worldManager.getMVWorld(player.getWorld()); + if (world == null) { + Logging.fine("Player is in a world that is not managed by Multiverse. Ignoring."); + return; + } + + if (!this.plugin.getPlayerActionChecker().hasAccessToWorld(player, world).isSuccessful()) { + player.sendMessage("[MV] - Sorry you can't be in this world anymore!"); + this.sendPlayerToDefaultWorld(player); + } + // Handle the Players GameMode setting for the new world. - this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld()); - playerWorld.put(p.getName(), p.getWorld().getName()); + this.handleGameModeAndFlight(event.getPlayer(), world); + playerWorld.put(player.getName(), player.getWorld().getName()); //TODO REMOVE } /** @@ -133,9 +147,14 @@ public class MVPlayerListener implements Listener { */ @EventHandler(priority = EventPriority.MONITOR) public void playerChangedWorld(PlayerChangedWorldEvent event) { - // Permissions now determine whether or not to handle a gamemode. - this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld()); - playerWorld.put(event.getPlayer().getName(), event.getPlayer().getWorld().getName()); + MVWorld world = worldManager.getMVWorld(event.getPlayer().getWorld()); + if (world == null) { + Logging.fine("Player is in a world that is not managed by Multiverse. Ignoring."); + return; + } + + this.handleGameModeAndFlight(event.getPlayer(), world); + playerWorld.put(event.getPlayer().getName(), event.getPlayer().getWorld().getName()); //TODO REMOVE } /** @@ -144,87 +163,54 @@ public class MVPlayerListener implements Listener { */ @EventHandler(priority = EventPriority.HIGHEST) public void playerTeleport(PlayerTeleportEvent event) { - Logging.finer("Got teleport event for player '" - + event.getPlayer().getName() + "' with cause '" + event.getCause() + "'"); - if (event.isCancelled()) { + if (event.isCancelled() || event.getTo() == null) { return; } + + Logging.fine("Got teleport event for player '" + + event.getPlayer().getName() + "' with cause '" + event.getCause() + "'"); + Player teleportee = event.getPlayer(); CommandSender teleporter = null; + + //TODO - Redo teleporter queue handling String teleporterName = MultiverseCore.getPlayerTeleporter(teleportee.getName()); - if (teleporterName != null) { - if (teleporterName.equals("CONSOLE")) { - Logging.finer("We know the teleporter is the console! Magical!"); - teleporter = this.plugin.getServer().getConsoleSender(); - } else { - teleporter = this.plugin.getServer().getPlayerExact(teleporterName); - } - } - Logging.finer("Inferred sender '" + teleporter + "' from name '" - + teleporterName + "', fetched from name '" + teleportee.getName() + "'"); - MVWorld fromWorld = this.worldManager.getMVWorld(event.getFrom().getWorld().getName()); - MVWorld toWorld = this.worldManager.getMVWorld(event.getTo().getWorld().getName()); - if (toWorld == null) { - Logging.fine("Player '" + teleportee.getName() + "' is teleporting to world '" - + event.getTo().getWorld().getName() + "' which is not managed by Multiverse-Core. No further " - + "actions will be taken by Multiverse-Core."); - return; - } - if (event.getFrom().getWorld().equals(event.getTo().getWorld())) { - // The player is Teleporting to the same world. - Logging.finer("Player '" + teleportee.getName() + "' is teleporting to the same world."); - this.stateSuccess(teleportee.getName(), toWorld.getAlias()); - return; - } - // TODO: Refactor these lines. - // Charge the teleporter - event.setCancelled(!pt.playerHasMoneyToEnter(fromWorld, toWorld, teleporter, teleportee, true)); - if (event.isCancelled() && teleporter != null) { - Logging.fine("Player '" + teleportee.getName() - + "' was DENIED ACCESS to '" + toWorld.getAlias() - + "' because '" + teleporter.getName() - + "' don't have the FUNDS required to enter it."); + if (teleporterName == null && !this.plugin.getMVConfig().getTeleportIntercept()) { + Logging.finer("Teleporting without intercepting."); return; } - // Check if player is allowed to enter the world if we're enforcing permissions - if (plugin.getMVConfig().getEnforceAccess()) { - event.setCancelled(!pt.playerCanGoFromTo(fromWorld, toWorld, teleporter, teleportee)); - if (event.isCancelled() && teleporter != null) { - Logging.fine("Player '" + teleportee.getName() - + "' was DENIED ACCESS to '" + toWorld.getAlias() - + "' because '" + teleporter.getName() - + "' don't have: multiverse.access." + event.getTo().getWorld().getName()); - return; - } + if (Objects.equals(teleporterName, "CONSOLE")) { + Logging.finer("We know the teleporter is the console! Magical!"); + teleporter = this.plugin.getServer().getConsoleSender(); } else { - Logging.fine("Player '" + teleportee.getName() - + "' was allowed to go to '" + toWorld.getAlias() + "' because enforceaccess is off."); + teleporter = this.plugin.getServer().getPlayerExact(teleporterName); + } + Logging.fine("Inferred sender '" + teleporter + "' from name '" + + teleporterName + "', fetched from name '" + teleportee.getName() + "'"); + + if (teleporter == null) { + Logging.finer("We don't know who the teleporter is, so we'll assume it's the player."); + teleporter = teleportee; } - // Does a limit actually exist? - if (toWorld.getPlayerLimit() > -1) { - // Are there equal or more people on the world than the limit? - if (toWorld.getCBWorld().getPlayers().size() >= toWorld.getPlayerLimit()) { - // Ouch the world is full, lets see if the player can bypass that limitation - if (!pt.playerCanBypassPlayerLimit(toWorld, teleporter, teleportee)) { - Logging.fine("Player '" + teleportee.getName() - + "' was DENIED ACCESS to '" + toWorld.getAlias() - + "' because the world is full and '" + teleporter.getName() - + "' doesn't have: mv.bypass.playerlimit." + event.getTo().getWorld().getName()); - event.setCancelled(true); - return; - } - } + MVWorld fromWorld = this.worldManager.getMVWorld(event.getFrom().getWorld()); + MVWorld toWorld = this.worldManager.getMVWorld(event.getTo().getWorld()); + ActionResponse actionCheckResponse = this.actionChecker.canGoFromToWorld(teleporter, teleportee, fromWorld, toWorld); + Logging.fine(actionCheckResponse.toString()); + if (!actionCheckResponse.isSuccessful()) { + tellReason(teleporter, teleportee, fromWorld, toWorld, actionCheckResponse); + event.setCancelled(true); + return; } - // By this point anything cancelling the event has returned on the method, meaning the teleport is a success \o/ - this.stateSuccess(teleportee.getName(), toWorld.getAlias()); - } + if (actionCheckResponse.hasResult(ActionCheckResult.ENOUGH_MONEY)) { + double price = toWorld.getPrice(); + Material currency = toWorld.getCurrency(); + this.plugin.getEconomist().payEntryFee((Player) teleporter, price, currency); + } - private void stateSuccess(String playerName, String worldName) { - Logging.fine("MV-Core is allowing Player '" + playerName - + "' to go to '" + worldName + "'."); + Logging.fine("MV-Core is allowing Player '" + teleportee.getName() + "' to go to '" + toWorld.getName() + "'."); } /** @@ -253,71 +239,37 @@ public class MVPlayerListener implements Listener { return; } } + /** * This method is called when a player actually portals via a vanilla style portal. * @param event The Event that was fired. */ @EventHandler(priority = EventPriority.HIGH) public void playerPortal(PlayerPortalEvent event) { - if (event.isCancelled() || (event.getFrom() == null)) { + if (event.isCancelled() || event.getFrom() == null || event.getTo() == null) { return; } - // The adjust should have happened much earlier. - if (event.getTo() == null) { + + MVWorld fromWorld = this.worldManager.getMVWorld(event.getFrom().getWorld()); + MVWorld toWorld = this.worldManager.getMVWorld(event.getTo().getWorld()); + ActionResponse actionCheckResponse = this.actionChecker.canGoFromToWorld(event.getPlayer(), fromWorld, toWorld); + Logging.fine(actionCheckResponse.toString()); + if (!actionCheckResponse.isSuccessful()) { + tellReason(event.getPlayer(), event.getPlayer(), fromWorld, toWorld, actionCheckResponse); + event.setCancelled(true); return; } - MVWorld fromWorld = this.worldManager.getMVWorld(event.getFrom().getWorld().getName()); - MVWorld toWorld = this.worldManager.getMVWorld(event.getTo().getWorld().getName()); - 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."); - return; - } - event.setCancelled(!pt.playerHasMoneyToEnter(fromWorld, toWorld, event.getPlayer(), event.getPlayer(), true)); - if (event.isCancelled()) { - Logging.fine("Player '" + event.getPlayer().getName() - + "' was DENIED ACCESS to '" + event.getTo().getWorld().getName() - + "' because they don't have the FUNDS required to enter."); - return; - } - if (plugin.getMVConfig().getEnforceAccess()) { - event.setCancelled(!pt.playerCanGoFromTo(fromWorld, toWorld, event.getPlayer(), event.getPlayer())); - if (event.isCancelled()) { - Logging.fine("Player '" + event.getPlayer().getName() - + "' was DENIED ACCESS to '" + event.getTo().getWorld().getName() - + "' because they don't have: multiverse.access." + event.getTo().getWorld().getName()); - } - } else { - Logging.fine("Player '" + event.getPlayer().getName() - + "' was allowed to go to '" + event.getTo().getWorld().getName() - + "' because enforceaccess is off."); - } + if (!this.plugin.getMVConfig().isUsingDefaultPortalSearch()) { event.setSearchRadius(this.plugin.getMVConfig().getPortalSearchRadius()); } } - private void sendPlayerToDefaultWorld(final Player player) { + private void sendPlayerToDefaultWorld(@NotNull Player player) { // Remove the player 1 tick after the login. I'm sure there's GOT to be a better way to do this... this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, - new Runnable() { - @Override - public void run() { - player.teleport(plugin.getMVWorldManager().getFirstSpawnWorld().getSpawnLocation()); - } - }, 1L); - } - - // FOLLOWING 2 Methods and Private class handle Per Player GameModes. - private void handleGameModeAndFlight(Player player, World world) { - - MVWorld mvWorld = this.worldManager.getMVWorld(world.getName()); - if (mvWorld != null) { - this.handleGameModeAndFlight(player, mvWorld); - } else { - Logging.finer("Not handling gamemode and flight for world '" + world.getName() - + "' not managed by Multiverse."); - } + () -> player.teleport(plugin.getMVWorldManager().getFirstSpawnWorld().getSpawnLocation()), + 1L); } /** @@ -325,40 +277,87 @@ public class MVPlayerListener implements Listener { * @param player The {@link Player}. * @param world The world the player is in. */ - public void handleGameModeAndFlight(final Player player, final MVWorld world) { + public void handleGameModeAndFlight(@NotNull Player player, @NotNull MVWorld world) { // We perform this task one tick later to MAKE SURE that the player actually reaches the // destination world, otherwise we'd be changing the player mode if they havent moved anywhere. - this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, - new Runnable() { - @Override - public void run() { - if (!MVPlayerListener.this.pt.playerCanIgnoreGameModeRestriction(world, player)) { - // Check that the player is in the new world and they haven't been teleported elsewhere or the event cancelled. - if (player.getWorld() == world.getCBWorld()) { - Logging.fine("Handling gamemode for player: %s, Changing to %s", player.getName(), world.getGameMode().toString()); - Logging.finest("From World: %s", player.getWorld()); - Logging.finest("To World: %s", world); - player.setGameMode(world.getGameMode()); - // Check if their flight mode should change - // TODO need a override permission for this - if (player.getAllowFlight() && !world.getAllowFlight() && player.getGameMode() != GameMode.CREATIVE) { - player.setAllowFlight(false); - if (player.isFlying()) { - player.setFlying(false); - } - } else if (world.getAllowFlight()) { - if (player.getGameMode() == GameMode.CREATIVE) { - player.setAllowFlight(true); - } - } - } else { - Logging.fine("The gamemode/allowfly was NOT changed for player '%s' because he is now in world '%s' instead of world '%s'", - player.getName(), player.getWorld().getName(), world.getName()); - } - } else { - Logging.fine("Player: " + player.getName() + " is IMMUNE to gamemode changes!"); - } - } - }, 1L); + this.plugin.getServer().getScheduler().scheduleSyncDelayedTask( + this.plugin, + ()-> applyGameModeAndFlight(player, world), + 1L); + } + + private void applyGameModeAndFlight(@NotNull Player player, @NotNull MVWorld world) { + if (MVPlayerListener.this.actionChecker.canKeepGameMode(player, world).isSuccessful()) { + Logging.fine("Player: " + player.getName() + " is IMMUNE to gamemode changes!"); + return; + } + + // Check that the player is in the new world and they haven't been teleported elsewhere or the event cancelled. + if (player.getWorld() != world.getCBWorld()) { + Logging.fine("The gamemode/allowfly was NOT changed for player '%s' because he is now in world '%s' instead of world '%s'", + player.getName(), player.getWorld().getName(), world.getName()); + return; + } + Logging.fine("Handling gamemode for player: %s, Changing to %s", player.getName(), world.getGameMode().toString()); + Logging.finest("From World: %s", player.getWorld()); + Logging.finest("To World: %s", world); + player.setGameMode(world.getGameMode()); + + // Check if their flight mode should change + // TODO need a override permission for this + if (player.getAllowFlight() && !world.getAllowFlight() && player.getGameMode() != GameMode.CREATIVE) { + player.setAllowFlight(false); + if (player.isFlying()) { + player.setFlying(false); + } + } else if (world.getAllowFlight()) { + if (player.getGameMode() == GameMode.CREATIVE) { + player.setAllowFlight(true); + } + } + } + + private void tellReason(@NotNull CommandSender sender, + @NotNull Player teleportee, + @Nullable MVWorld fromWorld, + @Nullable MVWorld toWorld, + @NotNull ActionResult result + ) { + BukkitCommandIssuer issuer = this.plugin.getMVCommandManager().getCommandIssuer(sender); + String targetName = issuer.getIssuer() == teleportee ? "You" : teleportee.getName(); + + if (result.hasResult(ActionCheckResult.NULL_DESTINATION)) { + issuer.sendMessage(targetName + " cannot be teleported to because the destination is null."); + return; + } + if (result.hasResult(ActionCheckResult.NULL_LOCATION)) { + issuer.sendMessage(targetName + " cannot be teleported to because the location is null."); + return; + } + if (result.hasResult(ActionCheckResult.NULL_WORLD)) { + issuer.sendMessage(targetName + " cannot be teleported because the world is null."); + return; + } + + if (result.hasResult(ActionCheckResult.NO_WORLD_ACCESS)) { + issuer.sendMessage(targetName + " cannot be teleported to because you does not have access to " + toWorld.getName()); + } + if (result.hasResult(ActionCheckResult.EXCEED_PLAYERLIMIT)) { + issuer.sendMessage(targetName + " cannot cannot enter " + toWorld.getName() + " because it is full."); + } + if (result.hasResult(ActionCheckResult.NOT_ENOUGH_MONEY)) { + issuer.sendMessage("You do not have enough money to pay for " + targetName + " to enter " + toWorld.getName()); + issuer.sendMessage("The entry fee required is " + this.plugin.getEconomist().formatPrice(toWorld)); + } + if (result.hasResult(ActionCheckResult.CANNOT_PAY_ENTRY_FEE)) { + issuer.sendMessage("You do not have the ability to pay the entry fee for " + targetName + " to enter " + toWorld.getName()); + } + if (result.hasResult(ActionCheckResult.BLACKLISTED)) { + if (toWorld.equals(fromWorld)) { + issuer.sendMessage(targetName + " cannot teleport within " + toWorld.getName() + " because it is blacklisted."); + } else { + issuer.sendMessage(fromWorld.getName() + " is blacklisted from teleporting to " + toWorld.getName()); + } + } } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/ActionCheckResult.java b/src/main/java/com/onarandombox/MultiverseCore/utils/ActionCheckResult.java new file mode 100644 index 00000000..b3ef6192 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/ActionCheckResult.java @@ -0,0 +1,56 @@ +package com.onarandombox.MultiverseCore.utils; + +import com.onarandombox.MultiverseCore.utils.action.ActionResult; + +public enum ActionCheckResult implements ActionResult { + NULL_WORLD(false), + NULL_LOCATION(false), + NULL_DESTINATION(false), + + CAN_USE_DESTINATION(true), + NO_DESTINATION_PERMISSION(false), + + NOT_MV_WORLD(true), + SAME_WORLD(true), + + HAS_WORLD_ACCESS(true), + NO_WORLD_ACCESS(false), + NO_ENFORCE_WORLD_ACCESS(true), + + ENOUGH_MONEY(true), + NOT_ENOUGH_MONEY(false), + EXEMPTED_FROM_ENTRY_FEE(true), + CANNOT_PAY_ENTRY_FEE(false), + FREE_ENTRY(true), + + WITHIN_PLAYERLIMIT(true), + EXCEED_PLAYERLIMIT(false), + BYPASS_PLAYERLIMIT(true), + + NOT_BLACKLISTED(true), + BLACKLISTED(false), + + KEEP_GAME_MODE(true), + ENFORCE_GAME_MODE(false), + ; + + private final boolean isSuccessful; + + ActionCheckResult(boolean isSuccessful) { + this.isSuccessful = isSuccessful; + } + + @Override + public String getName() { + return this.name(); + } + + public boolean isSuccessful() { + return isSuccessful; + } + + @Override + public boolean hasResult(ActionResult result) { + return result == this; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/MVPermissions.java b/src/main/java/com/onarandombox/MultiverseCore/utils/MVPermissions.java deleted file mode 100644 index 812a4d69..00000000 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/MVPermissions.java +++ /dev/null @@ -1,405 +0,0 @@ -/****************************************************************************** - * Multiverse 2 Copyright (c) the Multiverse Team 2011. * - * Multiverse 2 is licensed under the BSD License. * - * For more information please check the README.md file included * - * with this project. * - ******************************************************************************/ - -package com.onarandombox.MultiverseCore.utils; - -import java.util.List; - -import com.dumptruckman.minecraft.util.Logging; -import com.onarandombox.MultiverseCore.MultiverseCore; -import com.onarandombox.MultiverseCore.api.MVDestination; -import com.onarandombox.MultiverseCore.api.MVWorldManager; -import com.onarandombox.MultiverseCore.api.MVWorld; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.permissions.Permission; -import org.bukkit.permissions.PermissionDefault; - -/** - * Multiverse's permission checker - */ -public class MVPermissions { - - private MultiverseCore plugin; - private MVWorldManager worldMgr; - - public MVPermissions(MultiverseCore plugin) { - this.plugin = plugin; - this.worldMgr = plugin.getMVWorldManager(); - - } - - /** - * Check if a Player can ignore GameMode restrictions for world they travel to. - * - * @param p The {@link Player} to check. - * @param w The {@link MVWorld} the player wants to teleport to. - * @return True if they should bypass restrictions. - */ - public boolean canIgnoreGameModeRestriction(Player p, MVWorld w) { - return p.hasPermission("mv.bypass.gamemode." + w.getName()); - } - - /** - * Check if a Player can teleport to the Destination world from there current world. - * - * @param p The {@link Player} to check. - * @param w The {@link MVWorld} the player wants to teleport to. - * @return Whether the player can teleport to the given {@link MVWorld}. - */ - public boolean canTravelFromWorld(Player p, MVWorld w) { - List blackList = w.getWorldBlacklist(); - - boolean returnValue = true; - - for (String s : blackList) { - if (s.equalsIgnoreCase(p.getWorld().getName())) { - returnValue = false; - break; - } - } - - return returnValue; - } - - /** - * Checks if the specified {@link CommandSender} can travel to the specified {@link Location}. - * @param sender The {@link CommandSender}. - * @param location The {@link Location}. - * @return Whether the {@link CommandSender} can travel to the specified {@link Location}. - */ - public boolean canTravelFromLocation(CommandSender sender, Location location) { - // Now The Bed destination can return null now. - if (location == null) { - return false; - } - if (!(sender instanceof Player)) { - return true; - } - Player teleporter = (Player) sender; - if (!this.worldMgr.isMVWorld(location.getWorld().getName())) { - return false; - } - return canTravelFromWorld(teleporter, this.worldMgr.getMVWorld(location.getWorld().getName())); - } - - /** - * Check if the Player has the permissions to enter this world. - * - * @param p The {@link Player} player that wants to enter - * @param w The {@link MVWorld} he wants to enter - * @return Whether he has the permission to enter the world - */ - public boolean canEnterWorld(Player p, MVWorld w) { - // If we're not enforcing access, anyone can enter. - if (!plugin.getMVConfig().getEnforceAccess()) { - Logging.finest("EnforceAccess is OFF. Player was allowed in " + w.getAlias()); - return true; - } - return this.hasPermission(p, "multiverse.access." + w.getName(), false); - } - - private boolean canEnterLocation(Player p, Location l) { - if (l == null) { - return false; - } - String worldName = l.getWorld().getName(); - if (!this.plugin.getMVWorldManager().isMVWorld(worldName)) { - return false; - } - return this.hasPermission(p, "multiverse.access." + worldName, false); - } - - /** - * Check to see if a sender can enter a destination. - * The reason this is not a player, is it can be used to simply check permissions - * The console should, for exmaple, always see all worlds - * - * @param sender The CommandSender to check. - * @param d The destination they are requesting. - * @return True if that sender can go to that destination - */ - public boolean canEnterDestination(CommandSender sender, MVDestination d) { - if (!(sender instanceof Player)) { - return true; - } - Player p = (Player) sender; - if (d == null || d.getLocation(p) == null) { - return false; - } - String worldName = d.getLocation(p).getWorld().getName(); - if (!this.worldMgr.isMVWorld(worldName)) { - return false; - } - if (!canEnterLocation(p, d.getLocation(p))) { - return false; - } - return this.hasPermission(p, d.getRequiredPermission(), false); - } - - /** - * Tells a {@link CommandSender} why another {@link CommandSender} can or can not access a certain {@link MVDestination}. - * @param asker The {@link CommandSender} that's asking. - * @param playerInQuestion The {@link CommandSender} whose permissions we want to know. - * @param d The {@link MVDestination}. - */ - public void tellMeWhyICantDoThis(CommandSender asker, CommandSender playerInQuestion, MVDestination d) { - boolean cango = true; - if (!(playerInQuestion instanceof Player)) { - asker.sendMessage(String.format("The console can do %severything%s.", ChatColor.RED, ChatColor.WHITE)); - return; - } - Player p = (Player) playerInQuestion; - if (d == null) { - asker.sendMessage(String.format("The provided Destination is %sNULL%s, and therefore %sINVALID%s.", - ChatColor.RED, ChatColor.WHITE, ChatColor.RED, ChatColor.WHITE)); - cango = false; - } - // We know it'll be a player here due to the first line of this method. - if (d.getLocation(p) == null) { - asker.sendMessage(String.format( - "The player will spawn at an %sindeterminate location%s. Talk to the MV Devs if you see this", - ChatColor.RED, ChatColor.WHITE)); - cango = false; - } - String worldName = d.getLocation(p).getWorld().getName(); - if (!this.worldMgr.isMVWorld(worldName)) { - asker.sendMessage(String.format("The destination resides in a world(%s%s%s) that is not managed by Multiverse.", - ChatColor.AQUA, worldName, ChatColor.WHITE)); - asker.sendMessage(String.format("Type %s/mv import ?%s to see the import command's help page.", - ChatColor.DARK_AQUA, ChatColor.WHITE)); - cango = false; - } - if (!this.hasPermission(p, "multiverse.access." + worldName, false)) { - asker.sendMessage(String.format("The player (%s%s%s) does not have the required world entry permission (%s%s%s) to go to the destination (%s%s%s).", - ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE, - ChatColor.GREEN, "multiverse.access." + worldName, ChatColor.WHITE, - ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE)); - cango = false; - } - if (!this.hasPermission(p, d.getRequiredPermission(), false)) { - asker.sendMessage(String.format("The player (%s%s%s) does not have the required entry permission (%s%s%s) to go to the destination (%s%s%s).", - ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE, - ChatColor.GREEN, d.getRequiredPermission(), ChatColor.WHITE, - ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE)); - cango = false; - } - if (cango) { - asker.sendMessage(String.format("The player (%s%s%s) CAN go to the destination (%s%s%s).", - ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE, - ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE)); - } else { - asker.sendMessage(String.format("The player (%s%s%s) cannot access the destination %s%s%s. Therefore they can't use mvtp at all for this.", - ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE, - ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE)); - return; - } - if (!this.hasPermission(p, "multiverse.teleport.self." + d.getIdentifier(), false)) { - asker.sendMessage(String.format("The player (%s%s%s) does not have the required teleport permission (%s%s%s) to use %s/mvtp %s%s.", - ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE, - ChatColor.GREEN, "multiverse.teleport.self." + d.getIdentifier(), ChatColor.WHITE, - ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE)); - } else { - asker.sendMessage(String.format("The player (%s%s%s) has the required teleport permission (%s%s%s) to use %s/mvtp %s%s.", - ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE, - ChatColor.GREEN, "multiverse.teleport.self." + d.getIdentifier(), ChatColor.WHITE, - ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE)); - } - if (!this.hasPermission(p, "multiverse.teleport.other." + d.getIdentifier(), false)) { - asker.sendMessage(String.format("The player (%s%s%s) does not have the required teleport permission (%s%s%s) to send others to %s%s%s via mvtp.", - ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE, - ChatColor.GREEN, "multiverse.teleport.other." + d.getIdentifier(), ChatColor.WHITE, - ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE)); - } else { - asker.sendMessage(String.format("The player (%s%s%s) has required teleport permission (%s%s%s) to send others to %s%s%s via mvtp.", - ChatColor.AQUA, p.getDisplayName(), ChatColor.WHITE, - ChatColor.GREEN, "multiverse.teleport.other." + d.getIdentifier(), ChatColor.WHITE, - ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE)); - } - } - - /** - * Check to see if a player has a permission. - * - * @param sender Who is requesting the permission. - * @param node The permission node in string format; multiverse.core.list.worlds for example. - * @param isOpRequired deprecated This is not used for anything anymore. - * @return True if they have that permission or any parent. - */ - public boolean hasPermission(CommandSender sender, String node, boolean isOpRequired) { - if (!(sender instanceof Player)) { - return true; - } - // NO one can access a null permission (mainly used for destinations):w - if (node == null) { - return false; - } - // Everyone can access an empty permission - // Currently used for the PlayerDestination - if (node.equals("")) { - return true; - } - - return checkActualPermission(sender, node); - } - - // TODO: Better player checks, most likely not needed, but safer. - private boolean checkActualPermission(CommandSender sender, String node) { - Player player = (Player) sender; - - boolean hasPermission = sender.hasPermission(node); - if (!sender.isPermissionSet(node)) { - Logging.finer(String.format("The node [%s%s%s] was %sNOT%s set for [%s%s%s].", - ChatColor.RED, node, ChatColor.WHITE, ChatColor.RED, ChatColor.WHITE, ChatColor.AQUA, - player.getDisplayName(), ChatColor.WHITE)); - } - if (hasPermission) { - Logging.finer("Checking to see if player [" + player.getName() + "] has permission [" + node + "]... YES"); - } else { - Logging.finer("Checking to see if player [" + player.getName() + "] has permission [" + node + "]... NO"); - } - return hasPermission; - } - - /** - * Checks to see if the sender has any parent perms. - * Stops when it finds one or when there are no more parents. - * This method is recursive. - * - * @param sender Who is asking for the permission. - * @param node The permission node to check (possibly already a parent). - * @return True if they have any parent perm, false if none. - */ - // TODO remove this...? - private boolean hasAnyParentPermission(CommandSender sender, String node) { - String parentPerm = this.pullOneLevelOff(node); - // Base case - if (parentPerm == null) { - return false; - } - // If they have a parent, they're good - if (this.checkActualPermission(sender, parentPerm + ".*")) { - return true; - } - return hasAnyParentPermission(sender, parentPerm); - } - - /** - * Pulls one level off of a yaml style node. - * Given multiverse.core.list.worlds will return multiverse.core.list - * - * @param node The root node to check. - * @return The parent of the node - */ - private static String pullOneLevelOff(String node) { - if (node == null) { - return null; - } - int index = node.lastIndexOf("."); - if (index > 0) { - return node.substring(0, index); - } - return null; - } - - /** - * {@inheritDoc} - */ - public boolean hasAnyPermission(CommandSender sender, List nodes, boolean isOpRequired) { - for (String node : nodes) { - if (this.hasPermission(sender, node, isOpRequired)) { - return true; - } - } - return false; - } - - /** - * {@inheritDoc} - */ - public boolean hasAllPermission(CommandSender sender, List nodes, boolean isOpRequired) { - for (String node : nodes) { - if (!this.hasPermission(sender, node, isOpRequired)) { - return false; - } - } - return true; - } - - /** - * Adds a permission. - * @param string The permission as {@link String}. - * @param defaultValue The default-value. - * @return The permission as {@link Permission}. - */ - public Permission addPermission(String string, PermissionDefault defaultValue) { - if (this.plugin.getServer().getPluginManager().getPermission(string) == null) { - Permission permission = new Permission(string, defaultValue); - this.plugin.getServer().getPluginManager().addPermission(permission); - this.addToParentPerms(string); - } - return this.plugin.getServer().getPluginManager().getPermission(string); - } - - private void addToParentPerms(String permString) { - String permStringChopped = permString.replace(".*", ""); - - String[] seperated = permStringChopped.split("\\."); - String parentPermString = getParentPerm(seperated); - if (parentPermString == null) { - addToRootPermission("*", permStringChopped); - addToRootPermission("*.*", permStringChopped); - return; - } - Permission parentPermission = this.plugin.getServer().getPluginManager().getPermission(parentPermString); - // Creat parent and grandparents - if (parentPermission == null) { - parentPermission = new Permission(parentPermString); - this.plugin.getServer().getPluginManager().addPermission(parentPermission); - - this.addToParentPerms(parentPermString); - } - // Create actual perm. - Permission actualPermission = this.plugin.getServer().getPluginManager().getPermission(permString); - // Extra check just to make sure the actual one is added - if (actualPermission == null) { - - actualPermission = new Permission(permString); - this.plugin.getServer().getPluginManager().addPermission(actualPermission); - } - if (!parentPermission.getChildren().containsKey(permString)) { - parentPermission.getChildren().put(actualPermission.getName(), true); - this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(parentPermission); - } - } - - private void addToRootPermission(String rootPerm, String permStringChopped) { - Permission rootPermission = this.plugin.getServer().getPluginManager().getPermission(rootPerm); - if (rootPermission == null) { - rootPermission = new Permission(rootPerm); - this.plugin.getServer().getPluginManager().addPermission(rootPermission); - } - rootPermission.getChildren().put(permStringChopped + ".*", true); - this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(rootPermission); - } - - /** - * If the given permission was 'multiverse.core.tp.self', this would return 'multiverse.core.tp.*'. - */ - private static String getParentPerm(String[] seperated) { - if (seperated.length == 1) { - return null; - } - String returnString = ""; - for (int i = 0; i < seperated.length - 1; i++) { - returnString += seperated[i] + "."; - } - return returnString + "*"; - } -} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionTools.java b/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionTools.java deleted file mode 100644 index b6ab4895..00000000 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionTools.java +++ /dev/null @@ -1,302 +0,0 @@ -/****************************************************************************** - * Multiverse 2 Copyright (c) the Multiverse Team 2011. * - * Multiverse 2 is licensed under the BSD License. * - * For more information please check the README.md file included * - * with this project. * - ******************************************************************************/ - -package com.onarandombox.MultiverseCore.utils; - -import com.dumptruckman.minecraft.util.Logging; -import com.onarandombox.MultiverseCore.MultiverseCore; -import com.onarandombox.MultiverseCore.api.MVWorld; -import com.onarandombox.MultiverseCore.economy.MVEconomist; -import org.bukkit.Material; -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; -import org.bukkit.permissions.Permission; - -/** - * Utility-class for permissions. - */ -public class PermissionTools { - private MultiverseCore plugin; - - public PermissionTools(MultiverseCore plugin) { - this.plugin = plugin; - } - - /** - * Adds a permission to the parent-permissions. - * @param permString The new permission as {@link String}. - */ - public void addToParentPerms(String permString) { - String permStringChopped = permString.replace(".*", ""); - - String[] seperated = permStringChopped.split("\\."); - String parentPermString = getParentPerm(seperated); - if (parentPermString == null) { - addToRootPermission("*", permStringChopped); - addToRootPermission("*.*", permStringChopped); - return; - } - Permission parentPermission = this.plugin.getServer().getPluginManager().getPermission(parentPermString); - // Creat parent and grandparents - if (parentPermission == null) { - parentPermission = new Permission(parentPermString); - this.plugin.getServer().getPluginManager().addPermission(parentPermission); - - this.addToParentPerms(parentPermString); - } - // Create actual perm. - Permission actualPermission = this.plugin.getServer().getPluginManager().getPermission(permString); - // Extra check just to make sure the actual one is added - if (actualPermission == null) { - - actualPermission = new Permission(permString); - this.plugin.getServer().getPluginManager().addPermission(actualPermission); - } - if (!parentPermission.getChildren().containsKey(permString)) { - parentPermission.getChildren().put(actualPermission.getName(), true); - this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(parentPermission); - } - } - - private void addToRootPermission(String rootPerm, String permStringChopped) { - Permission rootPermission = this.plugin.getServer().getPluginManager().getPermission(rootPerm); - if (rootPermission == null) { - rootPermission = new Permission(rootPerm); - this.plugin.getServer().getPluginManager().addPermission(rootPermission); - } - rootPermission.getChildren().put(permStringChopped + ".*", true); - this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(rootPermission); - } - - /** - * If the given permission was 'multiverse.core.tp.self', this would return 'multiverse.core.tp.*'. - * - * @param separatedPermissionString The array of a dot separated perm string. - * @return The dot separated parent permission string. - */ - private static String getParentPerm(String[] separatedPermissionString) { - if (separatedPermissionString.length == 1) { - return null; - } - String returnString = ""; - for (int i = 0; i < separatedPermissionString.length - 1; i++) { - returnString += separatedPermissionString[i] + "."; - } - return returnString + "*"; - } - - /** - * Checks if the given {@link Player} has enough money to enter the specified {@link MVWorld}. - * @param fromWorld The {@link MVWorld} the player is coming from. - * @param toWorld The {@link MVWorld} the player is going to. - * @param teleporter The teleporter. - * @param teleportee The teleportee. - * @param pay If the player has to pay the money. - * @return True if the player can enter the world. - */ - public boolean playerHasMoneyToEnter(MVWorld fromWorld, MVWorld toWorld, CommandSender teleporter, Player teleportee, boolean pay) { - Player teleporterPlayer; - if (plugin.getMVConfig().getTeleportIntercept()) { - if (teleporter instanceof ConsoleCommandSender) { - return true; - } - - if (teleporter == null) { - teleporter = teleportee; - } - - if (!(teleporter instanceof Player)) { - return false; - } - teleporterPlayer = (Player) teleporter; - } else { - if (teleporter instanceof Player) { - teleporterPlayer = (Player) teleporter; - } else { - teleporterPlayer = null; - } - - // Old-style! - if (teleporterPlayer == null) { - return true; - } - } - - // If the toWorld isn't controlled by MV, - // We don't care. - if (toWorld == null) { - return true; - } - - // Only check payments if it's a different world: - if (!toWorld.equals(fromWorld)) { - final double price = toWorld.getPrice(); - // Don't bother checking economy stuff if it doesn't even cost to enter. - if (price == 0D) { - return true; - } - // If the player does not have to pay, return now. - if (this.plugin.getMVPerms().hasPermission(teleporter, toWorld.getExemptPermission().getName(), true)) { - return true; - } - - final MVEconomist economist = plugin.getEconomist(); - final Material currency = toWorld.getCurrency(); - final String formattedAmount = economist.formatPrice(price, currency); - - if (economist.isPlayerWealthyEnough(teleporterPlayer, price, currency)) { - if (pay) { - if (price < 0D) { - economist.deposit(teleporterPlayer, -price, currency); - } else { - economist.withdraw(teleporterPlayer, price, currency); - } - sendTeleportPaymentMessage(economist, teleporterPlayer, teleportee, toWorld.getColoredWorldString(), price, currency); - } - } else { - if (teleportee.equals(teleporter)) { - teleporterPlayer.sendMessage(economist.getNSFMessage(currency, - "You need " + formattedAmount + " to enter " + toWorld.getColoredWorldString())); - } else { - teleporterPlayer.sendMessage(economist.getNSFMessage(currency, - "You need " + formattedAmount + " to send " + teleportee.getName() + " to " + toWorld.getColoredWorldString())); - } - return false; - } - } - return true; - } - - private void sendTeleportPaymentMessage (MVEconomist economist, Player teleporterPlayer, Player teleportee, String toWorld, double price, Material currency) { - price = Math.abs(price); - if (teleporterPlayer.equals(teleportee)) { - teleporterPlayer.sendMessage("You were " + (price > 0D ? "charged " : "given ") + economist.formatPrice(price, currency) + " for teleporting to " + toWorld); - } else { - teleporterPlayer.sendMessage("You were " + (price > 0D ? "charged " : "given ") + economist.formatPrice(price, currency) + " for teleporting " + teleportee.getName() + " to " + toWorld); - } - } - - - /** - * Checks to see if player can go to a world given their current status. - *

- * The return is a little backwards, and will return a value safe for event.setCancelled. - * - * @param fromWorld The MultiverseWorld they are in. - * @param toWorld The MultiverseWorld they want to go to. - * @param teleporter The CommandSender that wants to send someone somewhere. If null, - * will be given the same value as teleportee. - * @param teleportee The player going somewhere. - * @return True if they can't go to the world, False if they can. - */ - public boolean playerCanGoFromTo(MVWorld fromWorld, MVWorld toWorld, CommandSender teleporter, Player teleportee) { - Logging.finest("Checking '" + teleporter + "' can send '" + teleportee + "' somewhere"); - - Player teleporterPlayer; - if (plugin.getMVConfig().getTeleportIntercept()) { - // The console can send anyone anywhere - if (teleporter instanceof ConsoleCommandSender) { - return true; - } - - // Make sure we have a teleporter of some kind, even if it's inferred to be the teleportee - if (teleporter == null) { - teleporter = teleportee; - } - - // Now make sure we can cast the teleporter to a player, 'cause I'm tired of console things now - if (!(teleporter instanceof Player)) { - return false; - } - teleporterPlayer = (Player) teleporter; - } else { - if (teleporter instanceof Player) { - teleporterPlayer = (Player) teleporter; - } else { - teleporterPlayer = null; - } - - // Old-style! - if (teleporterPlayer == null) { - return true; - } - } - - // Actual checks - if (toWorld != null) { - if (!this.plugin.getMVPerms().canEnterWorld(teleporterPlayer, toWorld)) { - if (teleportee.equals(teleporter)) { - teleporter.sendMessage("You don't have access to go here..."); - } else { - teleporter.sendMessage("You can't send " + teleportee.getName() + " here..."); - } - - return false; - } - } else { - // TODO: Determine if this value is false because a world didn't exist - // or if it was because a world wasn't imported. - return true; - } - if (fromWorld != null) { - if (fromWorld.getWorldBlacklist().contains(toWorld.getName())) { - if (teleportee.equals(teleporter)) { - teleporter.sendMessage("You don't have access to go to " + toWorld.getColoredWorldString() + " from " + fromWorld.getColoredWorldString()); - } else { - teleporter.sendMessage("You don't have access to send " + teleportee.getName() + " from " - + fromWorld.getColoredWorldString() + " to " + toWorld.getColoredWorldString()); - } - return false; - } - } - return true; - } - - /** - * Checks to see if a player can bypass the player limit. - * - * @param toWorld The world travelling to. - * @param teleporter The player that initiated the teleport. - * @param teleportee The player travelling. - * @return True if they can bypass the player limit. - */ - public boolean playerCanBypassPlayerLimit(MVWorld toWorld, CommandSender teleporter, Player teleportee) { - if (teleporter == null) { - teleporter = teleportee; - } - - if (!(teleporter instanceof Player)) { - return true; - } - - MVPermissions perms = plugin.getMVPerms(); - if (perms.hasPermission(teleportee, "mv.bypass.playerlimit." + toWorld.getName(), false)) { - return true; - } else { - teleporter.sendMessage("The world " + toWorld.getColoredWorldString() + " is full"); - return false; - } - } - - /** - * Checks to see if a player should bypass game mode restrictions. - * - * @param toWorld world travelling to. - * @param teleportee player travelling. - * @return True if they should bypass restrictions - */ - public boolean playerCanIgnoreGameModeRestriction(MVWorld toWorld, Player teleportee) { - if (toWorld != null) { - return this.plugin.getMVPerms().canIgnoreGameModeRestriction(teleportee, toWorld); - } else { - // TODO: Determine if this value is false because a world didn't exist - // or if it was because a world wasn't imported. - return true; - } - } -} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionsTool.java b/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionsTool.java new file mode 100644 index 00000000..3c5a5349 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/PermissionsTool.java @@ -0,0 +1,225 @@ +package com.onarandombox.MultiverseCore.utils; + +import com.dumptruckman.minecraft.util.Logging; +import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.Destination; +import com.onarandombox.MultiverseCore.api.MVWorld; +import com.onarandombox.MultiverseCore.destination.ParsedDestination; +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; +import org.bukkit.plugin.PluginManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PermissionsTool { + private static final String TELEPORT_PERM_PREFIX = "multiverse.teleport."; + + private final MultiverseCore plugin; + private PluginManager pluginManager; + private Permission worldAccessPermission; + private Permission bypassGameModePermission; + private Permission bypassEntryFeePermission; + private Permission bypassPlayerLimitPermission; + + public PermissionsTool(MultiverseCore plugin) { + this.plugin = plugin; + } + + public void setUpPermissions() { + this.pluginManager = this.plugin.getServer().getPluginManager(); + setUpWorldPermissionWildcards(); + } + + private void setUpWorldPermissionWildcards() { + this.worldAccessPermission = new Permission("multiverse.access.*", + "Allows access to all worlds", + PermissionDefault.OP); + this.bypassGameModePermission = new Permission("mv.bypass.gamemode.*", + "Allows players with this permission to ignore gamemode changes.", + PermissionDefault.FALSE); + this.bypassEntryFeePermission = new Permission("multiverse.exempt.*", + "A player who has this does not pay to enter this world, or use any MV portals in it", + PermissionDefault.OP); + this.bypassPlayerLimitPermission = new Permission("mv.bypass.playerlimit.*", + "A player who can enter this world regardless of whether its full", + PermissionDefault.OP); + + try { + pluginManager.addPermission(this.worldAccessPermission); + pluginManager.addPermission(this.bypassGameModePermission); + pluginManager.addPermission(this.bypassEntryFeePermission); + pluginManager.addPermission(this.bypassPlayerLimitPermission); + } catch (IllegalArgumentException e) { + Logging.finer("World permissions wildcard already registered."); + } + + Logging.finer("Registered world permissions wildcard."); + } + + public void registerMVWorldPermissions(MVWorld world) { + Permission accessPermission = new Permission("multiverse.access." + world.getName(), + "Allows access to " + world.getName(), + PermissionDefault.OP); + Permission ignorePermission = new Permission("mv.bypass.gamemode." + world.getName(), + "Allows players with this permission to ignore gamemode changes.", + PermissionDefault.FALSE); + Permission exemptPermission = new Permission("multiverse.exempt." + world.getName(), + "A player who has this does not pay to enter this world, or use any MV portals in it " + world.getName(), + PermissionDefault.OP); + Permission playerLimitPermissions = new Permission("mv.bypass.playerlimit." + world.getName(), + "A player who can enter this world regardless of whether its full", + PermissionDefault.OP); + + try { + pluginManager.addPermission(accessPermission); + pluginManager.addPermission(ignorePermission); + pluginManager.addPermission(exemptPermission); + pluginManager.addPermission(playerLimitPermissions); + } catch (IllegalArgumentException e) { + Logging.finer("World permissions already registered for '" + world.getName() + "'"); + return; + } + + accessPermission.addParent(this.worldAccessPermission, true); + ignorePermission.addParent(this.bypassGameModePermission, true); + exemptPermission.addParent(this.bypassEntryFeePermission, true); + playerLimitPermissions.addParent(this.bypassPlayerLimitPermission, true); + + Logging.finer("Registered permissions for '" + world.getName() + "'"); + } + + public void removeMVWorldPermissions(MVWorld world) { + Permission accessPermission = pluginManager.getPermission("multiverse.access." + world.getName()); + if (accessPermission != null) { + this.worldAccessPermission.getChildren().remove(accessPermission.getName()); + pluginManager.removePermission(accessPermission); + } + Permission ignorePermission = pluginManager.getPermission("mv.bypass.gamemode." + world.getName()); + if (ignorePermission != null) { + this.bypassGameModePermission.getChildren().remove(ignorePermission.getName()); + pluginManager.removePermission(ignorePermission); + } + Permission exemptPermission = pluginManager.getPermission("multiverse.exempt." + world.getName()); + if (exemptPermission != null) { + this.bypassEntryFeePermission.getChildren().remove(exemptPermission.getName()); + pluginManager.removePermission(exemptPermission); + } + Permission playerLimitPermissions = pluginManager.getPermission("mv.bypass.playerlimit." + world.getName()); + if (playerLimitPermissions != null) { + this.bypassPlayerLimitPermission.getChildren().remove(playerLimitPermissions.getName()); + pluginManager.removePermission(playerLimitPermissions); + } + } + + public void removeAllMVWorldPermissions() { + this.worldAccessPermission.getChildren().keySet().forEach(pluginManager::removePermission); + this.bypassGameModePermission.getChildren().keySet().forEach(pluginManager::removePermission); + this.bypassEntryFeePermission.getChildren().keySet().forEach(pluginManager::removePermission); + this.bypassPlayerLimitPermission.getChildren().keySet().forEach(pluginManager::removePermission); + + pluginManager.removePermission(this.worldAccessPermission); + pluginManager.removePermission(this.bypassGameModePermission); + pluginManager.removePermission(this.bypassEntryFeePermission); + pluginManager.removePermission(this.bypassPlayerLimitPermission); + + setUpWorldPermissionWildcards(); + } + + public void registerDestinationTeleportPermissions(Destination destination) { + try { + pluginManager.addPermission(new Permission(TELEPORT_PERM_PREFIX + "self." + destination.getIdentifier(), PermissionDefault.OP)); + pluginManager.addPermission(new Permission(TELEPORT_PERM_PREFIX + "other." + destination.getIdentifier(), PermissionDefault.OP)); + pluginManager.addPermission(new Permission(TELEPORT_PERM_PREFIX + "self." + destination.getIdentifier() + ".*", PermissionDefault.OP)); + pluginManager.addPermission(new Permission(TELEPORT_PERM_PREFIX + "other." + destination.getIdentifier() + ".*", PermissionDefault.OP)); + } catch (IllegalArgumentException e) { + Logging.finer("Destination permissions already registered for '" + destination.getIdentifier() + "'"); + } + Logging.finer("Registered permissions for '" + destination.getIdentifier() + "'"); + } + + public void registerFinerDestinationTeleportPermissions(Destination destination, String finerSuffix) { + String finerPermissionName = TELEPORT_PERM_PREFIX + "self." + destination.getIdentifier() + "." + finerSuffix; + if (pluginManager.getPermission(finerPermissionName) != null) { + return; + } + Permission permission = pluginManager.getPermission(TELEPORT_PERM_PREFIX + "self." + destination.getIdentifier() + ".*"); + if (permission == null) { + return; + } + + Permission finerPermission = new Permission(finerPermissionName, PermissionDefault.OP); + try { + pluginManager.addPermission(finerPermission); + return; + } catch (IllegalArgumentException e) { + Logging.finer("Finer destination permissions already registered for '" + destination.getIdentifier() + "'"); + } + + finerPermission.addParent(permission, true); + Logging.finer("Registered finer permissions '" + finerPermissionName + "' for '" + destination.getIdentifier() + "'"); + } + + public boolean hasBypassPlayerLimit(@NotNull CommandSender sender, @NotNull MVWorld toWorld) { + return hasPermission(sender, "mv.bypass.playerlimit." + toWorld.getName()); + } + + public boolean hasBypassEntryFee(@NotNull CommandSender sender, @NotNull MVWorld toWorld) { + return hasPermission(sender, "multiverse.exempt." + toWorld.getName()); + } + + public boolean hasBypassGameModeEnforcement(@NotNull CommandSender sender, @NotNull MVWorld toWorld) { + return hasPermission(sender, "mv.bypass.gamemode." + toWorld.getName()); + } + + public boolean hasWorldAccess(@NotNull CommandSender sender, @NotNull MVWorld toWorld) { + return hasPermission(sender, "multiverse.access." + toWorld.getName()); + } + + public boolean hasDestinationTeleportPermission(@NotNull CommandSender teleportee, @NotNull Destination destination) { + return hasDestinationTeleportPermission(null, teleportee, destination); + } + + public boolean hasDestinationTeleportPermission(@Nullable CommandSender teleporter, + @NotNull CommandSender teleportee, + @NotNull Destination destination + ) { + if (teleporter == null || teleportee.equals(teleporter)) { + return hasPermission(teleportee, TELEPORT_PERM_PREFIX + "self." + destination.getIdentifier()); + } + return hasPermission(teleporter, TELEPORT_PERM_PREFIX + "other." + destination.getIdentifier()); + } + + public boolean hasFinerDestinationTeleportPermission(@NotNull CommandSender teleportee, @NotNull ParsedDestination destination) { + return hasFinerDestinationTeleportPermission(null, teleportee, destination); + } + + public boolean hasFinerDestinationTeleportPermission(@Nullable CommandSender teleporter, + @NotNull CommandSender teleportee, + @NotNull ParsedDestination destination + ) { + if (teleporter == null || teleportee.equals(teleporter)) { + return hasPermission(teleportee, TELEPORT_PERM_PREFIX + "self." + + destination.getDestination().getIdentifier() + "." + + destination.getDestinationInstance().getFinerPermissionSuffix()); + } + return hasPermission(teleporter, TELEPORT_PERM_PREFIX + "other." + + destination.getDestination().getIdentifier() + "." + + destination.getDestinationInstance().getFinerPermissionSuffix()); + } + + public boolean hasAnyDestinationTeleportPermissions(@NotNull CommandSender sender) { + return this.plugin.getDestinationsProvider().getRegisteredDestinations().stream() + .anyMatch(destination -> hasDestinationTeleportPermission(sender, this.plugin.getServer().getConsoleSender(), destination) + || hasDestinationTeleportPermission(sender, destination)); + } + + private boolean hasPermission(@NotNull CommandSender sender, @NotNull String permission) { + if (sender.hasPermission(permission)) { + Logging.finer("Checking to see if sender [" + sender.getName() + "] has permission [" + permission + "]... YES"); + return true; + } + Logging.finer("Checking to see if sender [" + sender.getName() + "] has permission [" + permission + "]... NO"); + return false; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/PlayerActionChecker.java b/src/main/java/com/onarandombox/MultiverseCore/utils/PlayerActionChecker.java new file mode 100644 index 00000000..d703aabe --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/PlayerActionChecker.java @@ -0,0 +1,181 @@ +package com.onarandombox.MultiverseCore.utils; + +import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.MVWorld; +import com.onarandombox.MultiverseCore.api.MVWorldManager; +import com.onarandombox.MultiverseCore.destination.ParsedDestination; +import com.onarandombox.MultiverseCore.utils.action.ActionResponse; +import com.onarandombox.MultiverseCore.world.configuration.EntryFee; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PlayerActionChecker { + private final MultiverseCore plugin; + private final MVWorldManager worldManager; + private final PermissionsTool permissionsTool; + + public PlayerActionChecker(MultiverseCore plugin) { + this.plugin = plugin; + this.worldManager = plugin.getMVWorldManager(); + this.permissionsTool = plugin.getPermissionsTool(); + } + + public ActionCheckResult canUseDestinationToTeleport(@NotNull Player teleportee, @Nullable ParsedDestination destination){ + return canUseDestinationToTeleport(null, teleportee, destination); + } + + public ActionCheckResult canUseDestinationToTeleport(@Nullable CommandSender teleporter, + @NotNull CommandSender teleportee, + @Nullable ParsedDestination destination + ) { + if (destination == null) { + return ActionCheckResult.NULL_DESTINATION; + } + if (!permissionsTool.hasDestinationTeleportPermission( + teleporter == null ? teleportee : teleporter, + teleportee, + destination.getDestination()) + ) { + return ActionCheckResult.NO_DESTINATION_PERMISSION; + } + //TODO Config whether to use finer permission + return permissionsTool.hasFinerDestinationTeleportPermission(teleporter, teleportee, destination) + ? ActionCheckResult.CAN_USE_DESTINATION : ActionCheckResult.NO_DESTINATION_PERMISSION; + } + + public ActionResponse canGoToDestination(@NotNull Player teleportee, @Nullable ParsedDestination destination){ + return canGoToDestination(null, teleportee, destination); + } + + public ActionResponse canGoToDestination(@Nullable CommandSender teleporter, + @NotNull Player teleportee, + @Nullable ParsedDestination destination + ) { + if (destination == null) { + return new ActionResponse().addResult(ActionCheckResult.NULL_DESTINATION); + } + Location location = destination.getDestinationInstance().getLocation(teleportee); + if (location == null) { + return new ActionResponse().addResult(ActionCheckResult.NULL_LOCATION); + } + return canGoToLocation(teleporter, teleportee, location); + } + + public ActionResponse canGoToLocation(@NotNull Player teleportee, @Nullable Location location){ + return canGoToLocation(null, teleportee, location); + } + + public ActionResponse canGoToLocation(@Nullable CommandSender teleporter, + @NotNull Player teleportee, + @Nullable Location location + ) { + if (location == null) { + return new ActionResponse().addResult(ActionCheckResult.NULL_LOCATION); + } + MVWorld toWorld = this.worldManager.getMVWorld(location.getWorld()); + return canEnterWorld(teleporter, teleportee, toWorld); + } + + public ActionResponse canEnterWorld(@NotNull Player player, @NotNull MVWorld toWorld) { + return canEnterWorld(null, player, toWorld); + } + + public ActionResponse canEnterWorld(@Nullable CommandSender teleporter, + @NotNull Player player, + @NotNull MVWorld toWorld + ) { + MVWorld fromWorld = this.worldManager.getMVWorld(player.getWorld()); + return canGoFromToWorld(teleporter, player, fromWorld, toWorld); + } + + public ActionResponse canGoFromToWorld(@NotNull CommandSender teleportee, @Nullable MVWorld fromWorld, @NotNull MVWorld toWorld) { + return canGoFromToWorld(null, teleportee, fromWorld, toWorld); + } + + public ActionResponse canGoFromToWorld(@Nullable CommandSender teleporter, + @NotNull CommandSender teleportee, + @Nullable MVWorld fromWorld, + @Nullable MVWorld toWorld + ) { + ActionResponse response = new ActionResponse(); + if (toWorld == null) { + return new ActionResponse().addResult(ActionCheckResult.NOT_MV_WORLD); + } + if (toWorld.equals(fromWorld)) { + return response.addResult(ActionCheckResult.SAME_WORLD) + .then(() -> isNotBlacklisted(fromWorld, toWorld)); + } + + CommandSender targetSender = (teleporter == null) ? teleportee : teleporter; + + return response.then(() -> hasAccessToWorld(targetSender, toWorld)) + .then(() -> isWithinPlayerLimit(targetSender, toWorld)) + .then(() -> isNotBlacklisted(fromWorld, toWorld)) + .then(() -> hasMoneyToEnterWorld(targetSender, toWorld)); + } + + public ActionCheckResult hasAccessToWorld(@NotNull CommandSender sender, @NotNull MVWorld toWorld) { + if (!this.plugin.getMVConfig().getEnforceAccess()) { + return ActionCheckResult.NO_ENFORCE_WORLD_ACCESS; + } + return permissionsTool.hasWorldAccess(sender, toWorld) + ? ActionCheckResult.HAS_WORLD_ACCESS : ActionCheckResult.NO_WORLD_ACCESS; + } + + public ActionCheckResult hasMoneyToEnterWorld(@NotNull CommandSender sender, @NotNull MVWorld toWorld) { + if (sender instanceof ConsoleCommandSender || sender instanceof BlockCommandSender) { + return ActionCheckResult.EXEMPTED_FROM_ENTRY_FEE; + } + if (!(sender instanceof Player)) { + return ActionCheckResult.CANNOT_PAY_ENTRY_FEE; + } + + double price = toWorld.getPrice(); + Material currency = toWorld.getCurrency(); + if (price == 0D && (currency == null || currency == EntryFee.DISABLED_MATERIAL)) { + return ActionCheckResult.FREE_ENTRY; + } + + Player player = (Player) sender; + if (permissionsTool.hasBypassEntryFee(player, toWorld)) { + return ActionCheckResult.EXEMPTED_FROM_ENTRY_FEE; + } + + return this.plugin.getEconomist().isPlayerWealthyEnough(player, price, currency) + ? ActionCheckResult.ENOUGH_MONEY : ActionCheckResult.NOT_ENOUGH_MONEY; + } + + public ActionCheckResult isWithinPlayerLimit(@NotNull CommandSender sender, @NotNull MVWorld toWorld) { + if (toWorld.getPlayerLimit() < 0 || toWorld.getCBWorld().getPlayers().size() <= toWorld.getPlayerLimit()) { + return ActionCheckResult.WITHIN_PLAYERLIMIT; + } + return permissionsTool.hasBypassPlayerLimit(sender, toWorld) + ? ActionCheckResult.BYPASS_PLAYERLIMIT : ActionCheckResult.EXCEED_PLAYERLIMIT; + } + + public ActionCheckResult isNotBlacklisted(@NotNull Player player, @NotNull MVWorld toWorld) { + MVWorld fromWorld = this.worldManager.getMVWorld(player.getWorld()); + return isNotBlacklisted(fromWorld, toWorld); + } + + public ActionCheckResult isNotBlacklisted(@Nullable MVWorld fromWorld, @NotNull MVWorld toWorld) { + if (fromWorld == null) { + // No blacklisting if the player is not in a MV world + return ActionCheckResult.NOT_BLACKLISTED; + } + return toWorld.getWorldBlacklist().contains(fromWorld.getName()) + ? ActionCheckResult.BLACKLISTED : ActionCheckResult.NOT_BLACKLISTED; + } + + public ActionCheckResult canKeepGameMode(@NotNull CommandSender sender, @NotNull MVWorld toWorld) { + //TODO: Add config option disable game mode enforcement + return permissionsTool.hasBypassGameModeEnforcement(sender, toWorld) + ? ActionCheckResult.KEEP_GAME_MODE : ActionCheckResult.ENFORCE_GAME_MODE; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/action/ActionResponse.java b/src/main/java/com/onarandombox/MultiverseCore/utils/action/ActionResponse.java new file mode 100644 index 00000000..949be58d --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/action/ActionResponse.java @@ -0,0 +1,64 @@ +package com.onarandombox.MultiverseCore.utils.action; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +public class ActionResponse implements ActionResult { + private final Set results; + private final boolean continueIfFail; + + private boolean isSuccessful = true; + + public ActionResponse() { + this(false); + } + + public ActionResponse(boolean continueIfFail) { + this.results = new HashSet<>(); + this.continueIfFail = continueIfFail; + } + + public ActionResponse then(Supplier resultSupplier) { + if (!continueIfFail && !isSuccessful) { + return this; + } + return addResult(resultSupplier.get()); + } + + public ActionResponse addResult(ActionResult result) { + if (!continueIfFail && !isSuccessful) { + return this; + } + + results.add(result); + if (!result.isSuccessful()) { + isSuccessful = false; + } + return this; + } + + @Override + public String getName() { + return results.stream().map(ActionResult::getName).collect(Collectors.joining(", ")); + } + + public boolean isSuccessful() { + return isSuccessful; + } + + @Override + public boolean hasResult(ActionResult result) { + return results.contains(result); + } + + @Override + public String toString() { + return "ActionResponse{" + + "results=" + getName() + + "; continueIfFail=" + continueIfFail + + "; isSuccessful=" + isSuccessful + + '}'; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/action/ActionResult.java b/src/main/java/com/onarandombox/MultiverseCore/utils/action/ActionResult.java new file mode 100644 index 00000000..a617f729 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/action/ActionResult.java @@ -0,0 +1,9 @@ +package com.onarandombox.MultiverseCore.utils.action; + +public interface ActionResult { + String getName(); + + boolean isSuccessful(); + + boolean hasResult(ActionResult result); +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorld.java b/src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorld.java index 0790c668..0f1ac78d 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorld.java +++ b/src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorld.java @@ -38,8 +38,6 @@ import org.bukkit.World.Environment; import org.bukkit.WorldType; import org.bukkit.configuration.serialization.SerializableAs; import org.bukkit.entity.Player; -import org.bukkit.permissions.Permission; -import org.bukkit.permissions.PermissionDefault; import org.bukkit.util.Vector; import org.jetbrains.annotations.Nullable; @@ -87,7 +85,7 @@ public class SimpleMVWorld implements MVWorld { this.props.environment = world.getEnvironment(); this.props.seed = world.getSeed(); - this.initPerms(); + this.plugin.getPermissionsTool().registerMVWorldPermissions(this); this.props.flushChanges(); @@ -335,11 +333,6 @@ public class SimpleMVWorld implements MVWorld { } } - private Permission permission; - private Permission exempt; - private Permission ignoreperm; - private Permission limitbypassperm; - /** * Null-location. */ @@ -384,37 +377,6 @@ public class SimpleMVWorld implements MVWorld { }; } - /** - * Initializes permissions. - */ - private void initPerms() { - this.permission = new Permission("multiverse.access." + this.getName(), "Allows access to " + this.getName(), PermissionDefault.OP); - // This guy is special. He shouldn't be added to any parent perms. - this.ignoreperm = new Permission("mv.bypass.gamemode." + this.getName(), - "Allows players with this permission to ignore gamemode changes.", PermissionDefault.FALSE); - - this.exempt = new Permission("multiverse.exempt." + this.getName(), - "A player who has this does not pay to enter this world, or use any MV portals in it " + this.getName(), PermissionDefault.OP); - - this.limitbypassperm = new Permission("mv.bypass.playerlimit." + this.getName(), - "A player who can enter this world regardless of wether its full", PermissionDefault.OP); - try { - this.plugin.getServer().getPluginManager().addPermission(this.permission); - this.plugin.getServer().getPluginManager().addPermission(this.exempt); - this.plugin.getServer().getPluginManager().addPermission(this.ignoreperm); - this.plugin.getServer().getPluginManager().addPermission(this.limitbypassperm); - // Add the permission and exempt to parents. - this.addToUpperLists(this.permission); - - // Add ignore to it's parent: - this.ignoreperm.addParent("mv.bypass.gamemode.*", true); - // Add limit bypass to it's parent - this.limitbypassperm.addParent("mv.bypass.playerlimit.*", true); - } catch (IllegalArgumentException e) { - Logging.finer("Permissions nodes were already added for " + this.name); - } - } - private Location readSpawnFromWorld(World w) { Location location = w.getSpawnLocation(); // Set the worldspawn to our configspawn @@ -457,32 +419,6 @@ public class SimpleMVWorld implements MVWorld { return location; } - private void addToUpperLists(Permission perm) { - Permission all = this.plugin.getServer().getPluginManager().getPermission("multiverse.*"); - Permission allWorlds = this.plugin.getServer().getPluginManager().getPermission("multiverse.access.*"); - Permission allExemption = this.plugin.getServer().getPluginManager().getPermission("multiverse.exempt.*"); - - if (allWorlds == null) { - allWorlds = new Permission("multiverse.access.*"); - this.plugin.getServer().getPluginManager().addPermission(allWorlds); - } - allWorlds.getChildren().put(perm.getName(), true); - if (allExemption == null) { - allExemption = new Permission("multiverse.exempt.*"); - this.plugin.getServer().getPluginManager().addPermission(allExemption); - } - allExemption.getChildren().put(this.exempt.getName(), true); - if (all == null) { - all = new Permission("multiverse.*"); - this.plugin.getServer().getPluginManager().addPermission(all); - } - all.getChildren().put("multiverse.access.*", true); - all.getChildren().put("multiverse.exempt.*", true); - - this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(all); - this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(allWorlds); - } - /** * Copies all properties from another {@link SimpleMVWorld} object. * @param other The other world object. @@ -724,14 +660,6 @@ public class SimpleMVWorld implements MVWorld { return this.name; } - /** - * {@inheritDoc} - */ - @Override - public String getPermissibleName() { - return this.name.toLowerCase(); - } - /** * {@inheritDoc} */ @@ -912,14 +840,6 @@ public class SimpleMVWorld implements MVWorld { return this.props.setRespawnToWorld(respawnToWorld); } - /** - * {@inheritDoc} - */ - @Override - public Permission getAccessPermission() { - return this.permission; - } - /** * {@inheritDoc} */ @@ -952,14 +872,6 @@ public class SimpleMVWorld implements MVWorld { this.props.setPrice(price); } - /** - * {@inheritDoc} - */ - @Override - public Permission getExemptPermission() { - return this.exempt; - } - /** * {@inheritDoc} */ diff --git a/src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorldManager.java index 2129da1a..0f49eb7e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/world/SimpleMVWorldManager.java @@ -726,25 +726,7 @@ public class SimpleMVWorldManager implements MVWorldManager { // Force the worlds to be loaded, ie don't just load new worlds. if (forceLoad) { - // Remove all world permissions. - Permission allAccess = this.plugin.getServer().getPluginManager().getPermission("multiverse.access.*"); - Permission allExempt = this.plugin.getServer().getPluginManager().getPermission("multiverse.exempt.*"); - for (MVWorld w : this.worlds.values()) { - // Remove this world from the master list - if (allAccess != null) { - allAccess.getChildren().remove(w.getAccessPermission().getName()); - } - if (allExempt != null) { - allExempt.getChildren().remove(w.getAccessPermission().getName()); - } - this.plugin.getServer().getPluginManager().removePermission(w.getAccessPermission().getName()); - this.plugin.getServer().getPluginManager().removePermission(w.getExemptPermission().getName()); - // Special namespace for gamemodes - this.plugin.getServer().getPluginManager().removePermission("mv.bypass.gamemode." + w.getName()); - } - // Recalc the all permission - this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(allAccess); - this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(allExempt); + this.plugin.getPermissionsTool().removeAllMVWorldPermissions(); this.worlds.clear(); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/world/configuration/EntryFee.java b/src/main/java/com/onarandombox/MultiverseCore/world/configuration/EntryFee.java index de082605..436f46e1 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/world/configuration/EntryFee.java +++ b/src/main/java/com/onarandombox/MultiverseCore/world/configuration/EntryFee.java @@ -22,7 +22,7 @@ public class EntryFee extends SerializationConfig { @Nullable private Material currency; - private final Material DISABLED_MATERIAL = Material.AIR; + public static final Material DISABLED_MATERIAL = Material.AIR; public EntryFee() { super();