Compare commits

...
38 changed files with 1319 additions and 1288 deletions

No files matched your search

@@ -38,10 +38,8 @@ import com.onarandombox.MultiverseCore.commands.LoadCommand;
import com.onarandombox.MultiverseCore.commands.RegenCommand;
import com.onarandombox.MultiverseCore.commands.ReloadCommand;
import com.onarandombox.MultiverseCore.commands.RemoveCommand;
import com.onarandombox.MultiverseCore.commands.RootCommand;
import com.onarandombox.MultiverseCore.commands.TeleportCommand;
import com.onarandombox.MultiverseCore.commands.UnloadCommand;
import com.onarandombox.MultiverseCore.commands.UsageCommand;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.destination.core.AnchorDestination;
@@ -62,7 +60,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.permission.PermissionsRegistrar;
import com.onarandombox.MultiverseCore.utils.player.PlayerActionChecker;
import com.onarandombox.MultiverseCore.utils.TestingMode;
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
import com.onarandombox.MultiverseCore.utils.metrics.MetricsConfigurator;
@@ -90,7 +89,7 @@ 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 PlayerActionChecker playerActionChecker;
private SafeTTeleporter safeTTeleporter = new SimpleSafeTTeleporter(this);
private final UnsafeCallWrapper unsafeCallWrapper = new UnsafeCallWrapper(this);
private final MVWorldManager worldManager = new SimpleMVWorldManager(this);
@@ -102,7 +101,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 +136,9 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
*/
@Override
public void onEnable() {
PermissionsRegistrar.setup();
this.playerActionChecker = new PlayerActionChecker(this);
// Load our configs first as we need them for everything else.
this.loadConfigs();
if (this.multiverseConfig == null) {
@@ -187,6 +189,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);
@@ -288,8 +291,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
* {@inheritDoc}
*/
@Override
public MVPermissions getMVPerms() {
return this.mvPermissions;
public PlayerActionChecker getPlayerActionChecker() {
return playerActionChecker;
}
/**
@@ -7,14 +7,6 @@
package com.onarandombox.MultiverseCore.anchor;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
@@ -22,7 +14,15 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
/**
* Manages anchors.
@@ -140,18 +140,15 @@ public class AnchorManager {
if (ancLoc == null) {
continue;
}
String worldPerm = "multiverse.access." + ancLoc.getWorld().getName();
// Add to the list if we're not enforcing access
// OR
// We are enforcing access and the user has the permission.
if (!this.plugin.getMVConfig().getEnforceAccess() ||
(this.plugin.getMVConfig().getEnforceAccess() && p.hasPermission(worldPerm))) {
myAnchors.add(anchor);
} else {
Logging.finer(String.format("Not adding anchor %s to the list, user %s doesn't have the %s " +
"permission and 'enforceaccess' is enabled!",
anchor, p.getName(), worldPerm));
MVWorld mvWorld = this.plugin.getMVWorldManager().getMVWorld(ancLoc.getWorld());
if (mvWorld != null) {
if (!this.plugin.getPlayerActionChecker().hasAccessToWorld(p, mvWorld).asBoolean()) {
Logging.finer("Player '%s' does not have access to anchor '%s' in world '%s'.",
p.getName(), anchor, mvWorld.getName());
continue;
}
}
myAnchors.add(anchor);
}
return Collections.unmodifiableSet(myAnchors);
}
@@ -14,8 +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.UnsafeCallWrapper;
import com.onarandombox.MultiverseCore.utils.player.PlayerActionChecker;
/**
* Multiverse 2 Core API
@@ -44,14 +44,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 +105,13 @@ public interface MVCore extends MVPlugin {
*/
int getPluginCount();
/**
* Gets the {@link PlayerActionChecker} instance.
*
* @return The {@link PlayerActionChecker} instance.
*/
PlayerActionChecker getPlayerActionChecker();
/**
* Gets the {@link BlockSafety} this {@link MVCore} is using.
* @return The {@link BlockSafety} this {@link MVCore} is using.
@@ -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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* ex: e:0,0,0:50:50
*
* @return The savable config string.
*/
String toString();
/**
* Returns the permissions string required to go here.
* <p>
* ex: multiverse.access.world
* <p>
* 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?
* <p>
* If not, MV will blindly take people to the location specified.
*
* @return True if the SafeTeleporter will be used, false if not.
*/
boolean useSafeTeleporter();
}
@@ -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.
* <p>
* 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.
* <p>
@@ -0,0 +1,30 @@
package com.onarandombox.MultiverseCore.api.operation;
import org.jetbrains.annotations.Nullable;
/**
* Represents one or more action result.
*/
public interface OperationResult {
/**
* Get the name of the result.
*
* @return The name of the result.
*/
String getName();
/**
* Check if the result is successful.
*
* @return true if the result is successful.
*/
boolean asBoolean();
/**
* Check if the result is in the response.
*
* @param result The result to check.
* @return true if the result is in the response.
*/
boolean hasResult(@Nullable OperationResult result);
}
@@ -0,0 +1,123 @@
package com.onarandombox.MultiverseCore.api.operation;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A response that have multiple results.
*/
public class OperationResultChain implements OperationResult {
/**
* Create a new {@link OperationResultChain} instance.
* Does not continue if one result is not successful.
*
* @return The new {@link OperationResultChain} instance.
*/
public static OperationResultChain create() {
return new OperationResultChain(false);
}
/**
* Create a new {@link OperationResultChain} instance.
*
* @param continueIfFail If true, the response will continue to add results even if one of the results is not successful.
* @return The new {@link OperationResultChain} instance.
*/
public static OperationResultChain create(boolean continueIfFail) {
return new OperationResultChain(continueIfFail);
}
/**
* Create a response with a single result.
* Does not continue if one result is not successful.
*
* @param result The result.
* @return The new {@link OperationResultChain} instance.
*/
public static OperationResultChain of(OperationResult result) {
return new OperationResultChain(false).addResult(result);
}
private final Set<OperationResult> results;
private final boolean continueIfFail;
private boolean isSuccessful = true;
/**
* @param continueIfFail If true, the response will continue to add results even if one of the results is not successful.
*/
protected OperationResultChain(boolean continueIfFail) {
this.results = new HashSet<>();
this.continueIfFail = continueIfFail;
}
/**
* Add a result to the response.
*
* @param resultSupplier The supplier of the result.
* @return self
*/
public @NotNull OperationResultChain then(Supplier<OperationResult> resultSupplier) {
if (!continueIfFail && !isSuccessful) {
return this;
}
return addResult(resultSupplier.get());
}
/**
* Add a result to the response.
*
* @param result The result.
* @return self
*/
public @NotNull OperationResultChain addResult(OperationResult result) {
if (!continueIfFail && !isSuccessful) {
return this;
}
results.add(result);
if (!result.asBoolean()) {
isSuccessful = false;
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return results.stream().map(OperationResult::getName).collect(Collectors.joining(", "));
}
/**
* {@inheritDoc}
*/
@Override
public boolean asBoolean() {
return isSuccessful;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasResult(@Nullable OperationResult result) {
return results.contains(result);
}
@Override
public String toString() {
return "ActionResponse{" +
"results=" + getName() +
"; continueIfFail=" + continueIfFail +
"; isSuccessful=" + isSuccessful +
'}';
}
}
@@ -0,0 +1,86 @@
package com.onarandombox.MultiverseCore.api.operation;
import org.jetbrains.annotations.Nullable;
/**
* A simple implementation of {@link OperationResult}.
*/
public class SimpleOperationResult implements OperationResult {
/**
* Creates a new ActionResult that is successful with the given name.
*
* @param name The name of the result.
* @return The new ActionResult.
*/
public static OperationResult forSuccess(String name) {
return new SimpleOperationResult(name, true);
}
/**
* Creates a new ActionResult that is unsuccessful with the given name.
*
* @param name The name of the result.
* @return The new ActionResult.
*/
public static OperationResult forFailure(String name) {
return new SimpleOperationResult(name, false);
}
/**
* Creates a new ActionResult.
*
* @param name The name of the result.
* @param isSuccessful true if the result is successful.
* @return The new ActionResult.
*/
public static OperationResult of(String name, boolean isSuccessful) {
return new SimpleOperationResult(name, isSuccessful);
}
private final String name;
private final boolean booleanState;
/**
* Creates a new ActionResult.
*
* @param name The name of the result.
* @param isSuccessful true if the result is successful.
*/
protected SimpleOperationResult(String name, boolean isSuccessful) {
this.name = name;
this.booleanState = isSuccessful;
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return name;
}
/**
* {@inheritDoc}
*/
@Override
public boolean asBoolean() {
return booleanState;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasResult(@Nullable OperationResult result) {
return result == this;
}
@Override
public String toString() {
return "SimpleActionResult{" +
"name='" + name + '\'' +
", booleanState=" + booleanState +
'}';
}
}
@@ -0,0 +1,4 @@
/**
* This package contains the Operation API.
*/
package com.onarandombox.MultiverseCore.api.operation;
@@ -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().canUseParsedDestination(issuer.getIssuer(), player, destination).asBoolean()) {
issuer.sendMessage("You don't have permission to use this destination.");
}
if (!this.plugin.getPlayerActionChecker().canGoToDestination(issuer.getIssuer(), player, destination).asBoolean()) {
issuer.sendMessage("You don't have permission to teleport to this destination.");
}
}
}
@@ -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().canUseParsedDestination(issuer.getIssuer(), player, destination).asBoolean()) {
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,7 @@ public class TeleportCommand extends MultiverseCoreCommand {
@Override
public boolean hasPermission(CommandIssuer issuer) {
return this.plugin.getDestinationsProvider().hasAnyTeleportPermission(issuer);
return this.plugin.getDestinationsProvider().getRegisteredDestinations().stream()
.anyMatch(destination -> this.plugin.getPlayerActionChecker().canUseDestinationType(issuer.getIssuer(), destination).asBoolean());
}
}
@@ -16,7 +16,7 @@ import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.display.filters.ContentFilter;
import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter;
import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter;
import com.onarandombox.MultiverseCore.utils.PlayerFinder;
import com.onarandombox.MultiverseCore.utils.player.PlayerFinder;
import org.bukkit.GameRule;
import org.bukkit.entity.Player;
@@ -1,20 +1,19 @@
package com.onarandombox.MultiverseCore.destination;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
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 com.onarandombox.MultiverseCore.utils.permission.PermissionsRegistrar;
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 +22,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<String, Destination<?>> destinationMap;
@@ -45,13 +43,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()));
PermissionsRegistrar.registerDestinationPermissions(destination);
}
/**
@@ -65,8 +57,7 @@ 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.getPlayerActionChecker().canUseDestinationToTeleport(issuer, destination))
.map(destination -> destination.suggestDestinations(issuer, deststring).stream()
.map(s -> destination.getIdentifier() + SEPARATOR + s)
.collect(Collectors.toList()))
@@ -118,6 +109,10 @@ public class DestinationsProvider {
return this.destinationMap.get(identifier);
}
public @NotNull Collection<Destination<?>> getRegisteredDestinations() {
return Collections.unmodifiableCollection(this.destinationMap.values());
}
/**
* Teleports the teleportee to the destination.
*
@@ -129,9 +124,6 @@ public class DestinationsProvider {
@NotNull Player teleportee,
@NotNull ParsedDestination<?> destination
) {
if (!checkTeleportPermissions(teleporter, teleportee, destination)) {
return;
}
teleport(teleporter, teleportee, destination);
}
@@ -152,57 +144,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;
}
}
@@ -7,7 +7,7 @@ import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer;
import com.onarandombox.MultiverseCore.api.Destination;
import com.onarandombox.MultiverseCore.api.Teleporter;
import com.onarandombox.MultiverseCore.utils.PlayerFinder;
import com.onarandombox.MultiverseCore.utils.player.PlayerFinder;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -6,7 +6,7 @@ import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer;
import com.onarandombox.MultiverseCore.api.Destination;
import com.onarandombox.MultiverseCore.api.Teleporter;
import com.onarandombox.MultiverseCore.utils.PlayerFinder;
import com.onarandombox.MultiverseCore.utils.player.PlayerFinder;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -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,16 @@ public class MVEconomist {
return getVaultHandler().hasEconomy();
}
/**
* Formats the amount to a human readable currency string.
*
* @param world the world to get the price and currency from.
* @return the human readable currency string.
*/
public String formatPrice(MVWorld world) {
return formatPrice(world.getPrice(), world.getCurrency());
}
/**
* Formats the amount to a human readable currency string.
*
@@ -76,6 +87,35 @@ public class MVEconomist {
}
}
/**
* Pays for a given amount of currency either from the player's economy account or inventory if the currency.
*
* @param player the player to deposit currency into.
* @param world the world to take entry fee from.
*/
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.
*
@@ -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;
}
@@ -8,14 +8,24 @@
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.api.operation.OperationResultChain;
import com.onarandombox.MultiverseCore.api.operation.OperationResult;
import com.onarandombox.MultiverseCore.event.MVRespawnEvent;
import com.onarandombox.MultiverseCore.utils.PermissionTools;
import com.onarandombox.MultiverseCore.utils.player.PlayerActionChecker;
import com.onarandombox.MultiverseCore.utils.player.checkresult.BlacklistResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.EntryFeeResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.GameModeResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.NullPlaceResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.PlayerLimitResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.WorldAccessResult;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -30,6 +40,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 +49,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<String, String> playerWorld = new ConcurrentHashMap<String, String>();
private final Map<String, String> 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<String, String> getPlayerWorld() {
return playerWorld;
}
@@ -105,26 +118,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).asBoolean()) {
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 +152,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 +168,60 @@ 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());
OperationResultChain actionCheckResponse = this.actionChecker.canGoFromWorldToWorld(teleporter, teleportee, fromWorld, toWorld);
Logging.fine(actionCheckResponse.toString());
if (actionCheckResponse.hasResult(NullPlaceResult.NOT_MV_WORLD)) {
Logging.fine("Player '" + teleportee.getName() + "' is teleporting to a non-MV world. Ignoring.");
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.asBoolean()) {
tellReason(teleporter, teleportee, fromWorld, toWorld, actionCheckResponse);
event.setCancelled(true);
return;
}
private void stateSuccess(String playerName, String worldName) {
Logging.fine("MV-Core is allowing Player '" + playerName
+ "' to go to '" + worldName + "'.");
if (actionCheckResponse.hasResult(EntryFeeResult.ENOUGH_MONEY)) {
double price = toWorld.getPrice();
Material currency = toWorld.getCurrency();
this.plugin.getEconomist().payEntryFee((Player) teleporter, price, currency);
}
Logging.fine("MV-Core is allowing Player '" + teleportee.getName() + "' to go to '" + toWorld.getName() + "'.");
}
/**
@@ -253,71 +250,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());
OperationResultChain actionCheckResponse = this.actionChecker.canGoFromWorldToWorld(event.getPlayer(), event.getPlayer(), fromWorld, toWorld);
Logging.fine(actionCheckResponse.toString());
if (!actionCheckResponse.asBoolean()) {
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 +288,98 @@ 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) {
private 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);
}
/**
* Applies the gamemode and flight for the specified {@link Player}.
*
* @param player The {@link Player}.
* @param world The world the player is in.
*/
public void applyGameModeAndFlight(@NotNull Player player, @NotNull MVWorld world) {
GameModeResult keepGameModeResult = MVPlayerListener.this.actionChecker.canKeepGameMode(player, world);
if (keepGameModeResult.asBoolean()) {
Logging.fine("Player: " + player.getName() + " can keep their gamemode. " + "Reason: " + keepGameModeResult.getName());
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 --> To World: %s", player.getWorld());
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);
}
}
}
/**
* Sends the reason for the teleportation failure to the sender.
*
* @param sender The sender of the command.
* @param teleportee The player being teleported.
* @param fromWorld The world the player is teleporting from.
* @param toWorld The world the player is teleporting to.
* @param result The result of the teleportation.
*/
private void tellReason(@NotNull CommandSender sender,
@NotNull Player teleportee,
@Nullable MVWorld fromWorld,
@Nullable MVWorld toWorld,
@NotNull OperationResult result
) {
BukkitCommandIssuer issuer = this.plugin.getMVCommandManager().getCommandIssuer(sender);
String targetName = issuer.getIssuer() == teleportee ? "You" : teleportee.getName();
if (result.hasResult(NullPlaceResult.NULL_DESTINATION)) {
issuer.sendMessage(targetName + " cannot be teleported to because the destination is null.");
}
if (result.hasResult(NullPlaceResult.NULL_LOCATION)) {
issuer.sendMessage(targetName + " cannot be teleported to because the location is null.");
}
if (result.hasResult(NullPlaceResult.NULL_WORLD)) {
issuer.sendMessage(targetName + " cannot be teleported because the world is null.");
}
if (result.hasResult(WorldAccessResult.NO_WORLD_ACCESS)) {
issuer.sendMessage(targetName + " cannot be teleported to because you does not have access to " + toWorld.getName());
}
if (result.hasResult(PlayerLimitResult.EXCEED_PLAYERLIMIT)) {
issuer.sendMessage(targetName + " cannot enter " + toWorld.getName() + " because it is full.");
}
if (result.hasResult(EntryFeeResult.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(EntryFeeResult.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(BlacklistResult.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());
}
}
}
}
@@ -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<String> 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<String> nodes, boolean isOpRequired) {
for (String node : nodes) {
if (this.hasPermission(sender, node, isOpRequired)) {
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*/
public boolean hasAllPermission(CommandSender sender, List<String> 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 + "*";
}
}
@@ -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.
* <p>
* 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;
}
}
}
@@ -0,0 +1,81 @@
package com.onarandombox.MultiverseCore.utils.permission;
import com.dumptruckman.minecraft.util.Logging;
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.jetbrains.annotations.NotNull;
public class PermissionsChecker {
public static boolean hasWorldAccessPermission(@NotNull CommandSender sender, @NotNull MVWorld world) {
return hasPermission(sender, PermissionsRegistrar.worldAccessPermission, world.getName());
}
public static boolean hasWorldGamemodeBypassPermission(@NotNull CommandSender sender, @NotNull MVWorld world) {
return hasPermission(sender, PermissionsRegistrar.worldGamemodeBypassPermission, world.getName());
}
public static boolean hasWorldExemptPermission(@NotNull CommandSender sender, @NotNull MVWorld world) {
return hasPermission(sender, PermissionsRegistrar.worldExemptPermission, world.getName());
}
public static boolean hasWorldPlayerLimitBypassPermission(@NotNull CommandSender sender, @NotNull MVWorld world) {
return hasPermission(sender, PermissionsRegistrar.worldPlayerLimitBypassPermission, world.getName());
}
public static boolean hasTeleportSelfPermission(@NotNull CommandSender sender, @NotNull ParsedDestination<?> destination) {
return hasTeleportSelfPermission(sender, destination.getDestination());
}
public static boolean hasTeleportSelfPermission(@NotNull CommandSender sender, @NotNull Destination<?> destination) {
return hasPermission(sender, PermissionsRegistrar.teleportSelfPermission, destination.getIdentifier());
}
public static boolean hasTeleportSelfFinerPermission(@NotNull CommandSender sender, @NotNull ParsedDestination<?> destination) {
return hasPermission(sender, PermissionsRegistrar.teleportSelfPermission,
destination.getIdentifier() + "." + destination.getFinerPermissionSuffix());
}
public static boolean hasTeleportOtherPermission(@NotNull CommandSender sender, @NotNull ParsedDestination<?> destination) {
return hasTeleportOtherPermission(sender, destination.getDestination());
}
public static boolean hasTeleportOtherPermission(@NotNull CommandSender sender, @NotNull Destination<?> destination) {
return hasPermission(sender, PermissionsRegistrar.teleportOtherPermission, destination.getIdentifier());
}
public static boolean hasTeleportOtherFinerPermission(@NotNull CommandSender sender, @NotNull ParsedDestination<?> destination) {
return hasPermission(sender, PermissionsRegistrar.teleportOtherPermission,
destination.getIdentifier() + "." + destination.getFinerPermissionSuffix());
}
/**
* Internal method to check if a player has a permission and does logging.
*
* @param sender The sender to check.
* @param permission The permission to check.
* @param permissionSuffix The suffix to append to the permission.
* @return True if the player has the permission, false otherwise.
*/
private static boolean hasPermission(@NotNull CommandSender sender, @NotNull PrefixPermission permission, @NotNull String permissionSuffix) {
return hasPermission(sender, permission.getPermissionName(permissionSuffix));
}
/**
* Internal method to check if a player has a permission and does logging.
*
* @param sender The sender to check.
* @param permission The permission to check.
* @return True if the player has the permission, false otherwise.
*/
private static 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;
}
}
@@ -0,0 +1,77 @@
package com.onarandombox.MultiverseCore.utils.permission;
import java.util.ArrayList;
import java.util.List;
import com.onarandombox.MultiverseCore.api.Destination;
import com.onarandombox.MultiverseCore.api.MVWorld;
import org.bukkit.permissions.PermissionDefault;
public class PermissionsRegistrar {
private static List<PrefixPermission> worldPermissions;
private static List<PrefixPermission> destinationPermissions;
static PrefixPermission worldAccessPermission;
static PrefixPermission worldGamemodeBypassPermission;
static PrefixPermission worldExemptPermission;
static PrefixPermission worldPlayerLimitBypassPermission;
static PrefixPermission teleportSelfPermission;
static PrefixPermission teleportOtherPermission;
public static void setup() {
worldPermissions = new ArrayList<>() {{
add(worldAccessPermission = new PrefixPermission("multiverse.access.", "Allows access to a world."));
add(worldGamemodeBypassPermission = new PrefixPermission("mv.bypass.gamemode.", "Allows bypassing of gamemode restrictions.", PermissionDefault.FALSE));
add(worldExemptPermission = new PrefixPermission("multiverse.exempt.", "A player who has this does not pay to enter this world."));
add(worldPlayerLimitBypassPermission = new PrefixPermission("mv.bypass.playerlimit.", "Allows bypassing of player limit restrictions."));
}};
destinationPermissions = new ArrayList<>() {{
add(teleportSelfPermission = new PrefixPermission("multiverse.teleport.self.", "Allows teleporting to a world."));
add(teleportOtherPermission = new PrefixPermission("multiverse.teleport.other.", "Allows teleporting other players to a world."));
}};
}
public static void registerWorldPermissions(MVWorld world) {
registerPrefixPermissionList(worldPermissions, world.getName());
}
public static void registerDestinationPermissions(Destination<?> destination) {
registerPrefixPermissionList(destinationPermissions, destination.getIdentifier());
}
public static void removeWorldPermissions(MVWorld world) {
removePrefixPermissions(worldPermissions, world.getName());
}
public static void removeDestinationPermissions(Destination<?> destination) {
removePrefixPermissions(destinationPermissions, destination.getIdentifier());
}
public static void removeAllWorldPermissions() {
removeAllPrefixPermissions(worldPermissions);
}
public static void removeAllDestinationPermissions() {
removeAllPrefixPermissions(destinationPermissions);
}
private static void registerPrefixPermissionList(List<PrefixPermission> permissions, String permissionSuffix) {
for (PrefixPermission permission : permissions) {
permission.registerPermission(permissionSuffix);
}
}
private static void removePrefixPermissions(List<PrefixPermission> worldPermissions, String name) {
for (PrefixPermission permission : worldPermissions) {
permission.removePermission(name);
}
}
private static void removeAllPrefixPermissions(List<PrefixPermission> worldPermissions) {
for (PrefixPermission permission : worldPermissions) {
permission.removeAllPermissions();
}
}
}
@@ -0,0 +1,110 @@
package com.onarandombox.MultiverseCore.utils.permission;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.PluginManager;
public class PrefixPermission {
private final PluginManager pluginManager;
private final String permissionPrefix;
private final String description;
private final PermissionDefault permissionDefault;
private Permission wildcardPermission;
public PrefixPermission(String permissionPrefix, String description) {
this(permissionPrefix, description, PermissionDefault.OP);
}
public PrefixPermission(String permissionPrefix, String description, PermissionDefault permissionDefault) {
this.pluginManager = Bukkit.getServer().getPluginManager();
this.permissionPrefix = permissionPrefix;
this.description = description;
this.permissionDefault = permissionDefault;
}
public Permission registerPermission(String permissionSuffix) {
String permissionName = getPermissionName(permissionSuffix);
Permission permission = pluginManager.getPermission(permissionName);
if (permission != null) {
Logging.warning("Permission already registered: " + permission.getName());
return permission;
}
permission = new Permission(permissionName, description, permissionDefault);
pluginManager.addPermission(permission);
if (wildcardPermission == null) {
registerWildcardPermission();
}
permission.addParent(wildcardPermission, true);
pluginManager.recalculatePermissionDefaults(permission);
pluginManager.recalculatePermissionDefaults(wildcardPermission);
Logging.finest("Registered permission: " + permission.getName());
return permission;
}
public void registerWildcardPermission() {
String permissionName = getPermissionName("*");
wildcardPermission = pluginManager.getPermission(permissionName);
if (wildcardPermission != null) {
return;
}
wildcardPermission = new Permission(permissionName, description, permissionDefault);
pluginManager.addPermission(wildcardPermission);
pluginManager.recalculatePermissionDefaults(wildcardPermission);
}
public boolean removePermission(String permissionSuffix) {
String permissionName = getPermissionName(permissionSuffix);
Permission permission = pluginManager.getPermission(permissionName);
if (permission == null) {
return false;
}
try {
wildcardPermission.getChildren().remove(permission.getName());
pluginManager.removePermission(permission);
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
public boolean removeAllPermissions() {
try {
if (wildcardPermission != null) {
wildcardPermission.getChildren().forEach((child, value) -> pluginManager.removePermission(child));
pluginManager.removePermission(wildcardPermission);
}
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
public Permission getPermission(String permissionSuffix) {
return pluginManager.getPermission(permissionPrefix + permissionSuffix);
}
public Permission getWildcardPermission() {
return wildcardPermission;
}
public String getPermissionName(String permissionSuffix) {
return permissionPrefix + permissionSuffix;
}
public String getPermissionPrefix() {
return permissionPrefix;
}
public String getDescription() {
return description;
}
public PermissionDefault getPermissionDefault() {
return permissionDefault;
}
}
@@ -0,0 +1 @@
package com.onarandombox.MultiverseCore.utils.permission;
@@ -0,0 +1,270 @@
package com.onarandombox.MultiverseCore.utils.player;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.Destination;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.operation.OperationResultChain;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.utils.permission.PermissionsChecker;
import com.onarandombox.MultiverseCore.utils.player.checkresult.BlacklistResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.EntryFeeResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.GameModeResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.NullPlaceResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.PlayerLimitResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.UseDestinationResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.WorldAccessResult;
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;
/**
* Checks if a player can perform an action.
*/
public class PlayerActionChecker {
private final MultiverseCore plugin;
private final MVWorldManager worldManager;
/**
* Creates a new PlayerActionChecker.
*
* @param plugin The MultiverseCore plugin.
*/
public PlayerActionChecker(@NotNull MultiverseCore plugin) {
this.plugin = plugin;
this.worldManager = plugin.getMVWorldManager();
}
public UseDestinationResult canUseDestinationType(@NotNull CommandSender teleportee,
@NotNull Destination<?> destination
) {
return canUseDestinationType(teleportee, teleportee, destination);
}
public UseDestinationResult canUseDestinationType(@Nullable CommandSender teleporter,
@NotNull CommandSender teleportee,
@NotNull Destination<?> destination
) {
if (teleporter == null || teleporter.equals(teleportee)) {
return PermissionsChecker.hasTeleportSelfPermission(teleportee, destination)
? UseDestinationResult.CAN_USE_DESTINATION : UseDestinationResult.NO_DESTINATION_PERMISSION;
}
return PermissionsChecker.hasTeleportOtherPermission(teleporter, destination)
? UseDestinationResult.CAN_USE_DESTINATION : UseDestinationResult.NO_DESTINATION_PERMISSION;
}
public UseDestinationResult canUseParsedDestination(@NotNull CommandSender teleportee,
@NotNull ParsedDestination<?> destination
) {
return canUseParsedDestination(teleportee, teleportee, destination);
}
/**
* Checks if a player have permissions to teleport to a destination by another teleporter.
*
* @param teleporter The player who is teleporting the teleportee.
* @param teleportee The player to teleport.
* @param destination The destination to teleport to.
* @return The result of the check.
*/
public UseDestinationResult canUseParsedDestination(@Nullable CommandSender teleporter,
@NotNull CommandSender teleportee,
@NotNull ParsedDestination<?> destination
) {
UseDestinationResult result = canUseDestinationType(teleporter, teleportee, destination.getDestination());
if (!result.asBoolean()) {
return result;
}
if (teleporter == null || teleporter.equals(teleportee)) {
return PermissionsChecker.hasTeleportSelfFinerPermission(teleportee, destination)
? UseDestinationResult.CAN_USE_DESTINATION : UseDestinationResult.NO_DESTINATION_PERMISSION_FINER;
}
return PermissionsChecker.hasTeleportOtherFinerPermission(teleporter, destination)
? UseDestinationResult.CAN_USE_DESTINATION : UseDestinationResult.NO_DESTINATION_PERMISSION_FINER;
}
/**
* Checks if a player can teleport to a destination.
*
* @param teleporter The player who is teleporting the teleportee.
* @param teleportee The player to teleport.
* @param destination The destination to teleport to.
* @return One or more of the above action results.
*/
public OperationResultChain canGoToDestination(@Nullable CommandSender teleporter,
@NotNull Player teleportee,
@Nullable ParsedDestination<?> destination
) {
if (destination == null) {
return OperationResultChain.of(NullPlaceResult.NULL_DESTINATION);
}
Location location = destination.getDestinationInstance().getLocation(teleportee);
return canGoToLocation(teleporter, teleportee, location);
}
/**
* Checks if a player can teleport to a location.
*
* @param teleporter The player who is teleporting the teleportee.
* @param teleportee The player to teleport.
* @param location The location to teleport to.
* @return One or more of the above action results.
*/
public OperationResultChain canGoToLocation(@Nullable CommandSender teleporter,
@NotNull Player teleportee,
@Nullable Location location
) {
if (location == null) {
return OperationResultChain.of(NullPlaceResult.NULL_LOCATION);
}
if (location.getWorld() == null) {
return OperationResultChain.of(NullPlaceResult.NULL_WORLD);
}
MVWorld toWorld = this.worldManager.getMVWorld(location.getWorld());
return canGoToWorld(teleporter, teleportee, toWorld);
}
/**
* Checks if a player can teleport to a world.
*
* @param teleporter The player who is teleporting the teleportee.
* @param teleportee The player to teleport.
* @param toWorld The world to teleport to.
* @return One or more of the above action results.
*/
public OperationResultChain canGoToWorld(@Nullable CommandSender teleporter,
@NotNull Player teleportee,
@NotNull MVWorld toWorld
) {
MVWorld fromWorld = this.worldManager.getMVWorld(teleportee.getWorld());
return canGoFromWorldToWorld(teleporter, teleportee, fromWorld, toWorld);
}
/**
* Checks if a player can teleport from a world to another world.
*
* @param teleporter The player who is teleporting the teleportee.
* @param teleportee The player to teleport.
* @param toWorld The world to teleport to.
* @return One or more of the above action results.
*/
public OperationResultChain canGoFromWorldToWorld(@Nullable CommandSender teleporter,
@NotNull CommandSender teleportee,
@Nullable MVWorld fromWorld,
@Nullable MVWorld toWorld
) {
if (toWorld == null) {
return OperationResultChain.of(NullPlaceResult.NOT_MV_WORLD);
}
CommandSender targetSender = (teleporter == null) ? teleportee : teleporter;
return OperationResultChain.create(true)
.then(() -> hasAccessToWorld(targetSender, toWorld))
.then(() -> isWithinPlayerLimit(targetSender, toWorld))
.then(() -> isNotBlacklisted(fromWorld, toWorld))
.then(() -> hasMoneyToEnterWorld(targetSender, fromWorld, toWorld));
}
/**
* Checks if a player has access to a world.
*
* @param sender The sender to check.
* @param toWorld The world to teleport to.
* @return The action check result.
*/
public WorldAccessResult hasAccessToWorld(@NotNull CommandSender sender, @NotNull MVWorld toWorld) {
if (!this.plugin.getMVConfig().getEnforceAccess()) {
return WorldAccessResult.NO_ENFORCE_WORLD_ACCESS;
}
return PermissionsChecker.hasWorldAccessPermission(sender, toWorld)
? WorldAccessResult.HAS_WORLD_ACCESS : WorldAccessResult.NO_WORLD_ACCESS;
}
/**
* Checks if a player has access to a world.
*
* @param sender The sender to check.
* @param toWorld The world to teleport to.
* @return The action check result.
*/
public EntryFeeResult hasMoneyToEnterWorld(@NotNull CommandSender sender, @Nullable MVWorld fromWorld, @NotNull MVWorld toWorld) {
if (toWorld.equals(fromWorld)) {
return EntryFeeResult.SAME_WORLD;
}
if (sender instanceof ConsoleCommandSender || sender instanceof BlockCommandSender) {
return EntryFeeResult.EXEMPT_FROM_ENTRY_FEE;
}
if (!(sender instanceof Player)) {
return EntryFeeResult.CANNOT_PAY_ENTRY_FEE;
}
double price = toWorld.getPrice();
Material currency = toWorld.getCurrency();
if (price == 0D && (currency == null || currency == EntryFee.DISABLED_MATERIAL)) {
return EntryFeeResult.FREE_ENTRY;
}
Player player = (Player) sender;
if (PermissionsChecker.hasWorldExemptPermission(player, toWorld)) {
return EntryFeeResult.EXEMPT_FROM_ENTRY_FEE;
}
return this.plugin.getEconomist().isPlayerWealthyEnough(player, price, currency)
? EntryFeeResult.ENOUGH_MONEY : EntryFeeResult.NOT_ENOUGH_MONEY;
}
/**
* Checks if a player is within the player limit of a world.
*
* @param sender The sender to check.
* @param toWorld The world to teleport to.
* @return The action check result.
*/
public PlayerLimitResult isWithinPlayerLimit(@NotNull CommandSender sender, @NotNull MVWorld toWorld) {
if (toWorld.getPlayerLimit() <= -1) {
return PlayerLimitResult.NO_PLAYERLIMIT;
}
if (toWorld.getPlayerLimit() > toWorld.getCBWorld().getPlayers().size()) {
return PlayerLimitResult.WITHIN_PLAYERLIMIT;
}
return PermissionsChecker.hasWorldPlayerLimitBypassPermission(sender, toWorld)
? PlayerLimitResult.BYPASS_PLAYERLIMIT : PlayerLimitResult.EXCEED_PLAYERLIMIT;
}
/**
* Checks if a world is not blacklisted by another world.
*
* @param fromWorld The from world that is checked for blacklisting.
* @param toWorld The to world that has the blacklist.
* @return The action check result.
*/
public BlacklistResult isNotBlacklisted(@Nullable MVWorld fromWorld, @NotNull MVWorld toWorld) {
if (fromWorld == null) {
return BlacklistResult.UNKNOWN_SOURCE_WORLD;
}
// TODO: Add permission to bypass blacklist
return toWorld.getWorldBlacklist().contains(fromWorld.getName())
? BlacklistResult.BLACKLISTED : BlacklistResult.NOT_BLACKLISTED;
}
/**
* Checks if a player can keep their game mode on world change.
*
* @param player The sender to check.
* @param toWorld The world to teleport to.
* @return The action check result.
*/
public GameModeResult canKeepGameMode(@NotNull Player player, @NotNull MVWorld toWorld) {
if (player.getGameMode().equals(toWorld.getGameMode())) {
return GameModeResult.KEEP_GAME_MODE;
}
//TODO: Add config option disable game mode enforcement
return PermissionsChecker.hasWorldGamemodeBypassPermission(player, toWorld)
? GameModeResult.KEEP_GAME_MODE : GameModeResult.ENFORCE_GAME_MODE;
}
}
@@ -1,4 +1,4 @@
package com.onarandombox.MultiverseCore.utils;
package com.onarandombox.MultiverseCore.utils.player;
import java.util.ArrayList;
import java.util.List;
@@ -0,0 +1,32 @@
package com.onarandombox.MultiverseCore.utils.player.checkresult;
import com.onarandombox.MultiverseCore.api.operation.SimpleOperationResult;
public class BlacklistResult extends SimpleOperationResult {
/**
* Player coming from a world that is not managed by Multiverse.
*/
public static final BlacklistResult UNKNOWN_SOURCE_WORLD = new BlacklistResult("UNKNOWN_SOURCE_WORLD", true);
/**
* The player is not blacklisted.
*/
public static final BlacklistResult NOT_BLACKLISTED = new BlacklistResult("NOT_BLACKLISTED", true);
/**
* The player has permission to bypass the blacklist.
*/
public static final BlacklistResult BYPASSED_BLACKLISTED = new BlacklistResult("NOT_BLACKLISTED", true);
/**
* The player is blacklisted.
*/
public static final BlacklistResult BLACKLISTED = new BlacklistResult("DENIED", false);
/**
* {@inheritDoc}
*/
private BlacklistResult(String name, boolean isSuccessful) {
super(name, isSuccessful);
}
}
@@ -0,0 +1,42 @@
package com.onarandombox.MultiverseCore.utils.player.checkresult;
import com.onarandombox.MultiverseCore.api.operation.SimpleOperationResult;
public class EntryFeeResult extends SimpleOperationResult {
/**
* Sender is in the same world. Don't charge them.
*/
public static final EntryFeeResult SAME_WORLD = new EntryFeeResult("SAME_WORLD", true);
/**
* Free to enter the world.
*/
public static final EntryFeeResult FREE_ENTRY = new EntryFeeResult("FREE_ENTRY", true);
/**
* Sender has enough money to pay the entry fee.
*/
public static final EntryFeeResult ENOUGH_MONEY = new EntryFeeResult("ENOUGH_MONEY", true);
/**
* Sender is exempt from paying the entry fee.
*/
public static final EntryFeeResult EXEMPT_FROM_ENTRY_FEE = new EntryFeeResult("EXEMPT_FROM_ENTRY_FEE", true);
/**
* Sender does not have enough money to pay the entry fee.
*/
public static final EntryFeeResult NOT_ENOUGH_MONEY = new EntryFeeResult("NOT_ENOUGH_MONEY", false);
/**
* Sender cannot pay the entry fee.
*/
public static final EntryFeeResult CANNOT_PAY_ENTRY_FEE = new EntryFeeResult("CANNOT_PAY_ENTRY_FEE", false);
/**
* {@inheritDoc}
*/
private EntryFeeResult(String name, boolean isSuccessful) {
super(name, isSuccessful);
}
}
@@ -0,0 +1,32 @@
package com.onarandombox.MultiverseCore.utils.player.checkresult;
import com.onarandombox.MultiverseCore.api.operation.SimpleOperationResult;
public class GameModeResult extends SimpleOperationResult {
/**
* The player's game mode should be kept.
*/
public static final GameModeResult KEEP_GAME_MODE = new GameModeResult("KEEP_GAME_MODE", true);
/**
* The player has permission to bypass the game mode enforcement.
*/
public static final GameModeResult BYPASS_ENFORCE_GAME_MODE = new GameModeResult("BYPASS_ENFORCE_GAME_MODE", true);
/**
* The player's game mode is the same as the destination's game mode.
*/
public static final GameModeResult SAME_GAME_MODE = new GameModeResult("SAME_GAME_MODE", true);
/**
* The player's game mode should be enforced.
*/
public static final GameModeResult ENFORCE_GAME_MODE = new GameModeResult("ENFORCE_GAME_MODE", false);
/**
* {@inheritDoc}
*/
private GameModeResult(String name, boolean isSuccessful) {
super(name, isSuccessful);
}
}
@@ -0,0 +1,33 @@
package com.onarandombox.MultiverseCore.utils.player.checkresult;
import com.onarandombox.MultiverseCore.api.operation.OperationResult;
import com.onarandombox.MultiverseCore.api.operation.SimpleOperationResult;
public class NullPlaceResult extends SimpleOperationResult {
/**
* The target world is not a Multiverse world. So we just let the player go there without any checks
*/
public static final OperationResult NOT_MV_WORLD = new NullPlaceResult("NOT_MV_WORLD", true);
/**
* The target destination is null.
*/
public static final OperationResult NULL_DESTINATION = new NullPlaceResult("NULL_DESTINATION", false);
/**
* The target location is null.
*/
public static final OperationResult NULL_LOCATION = new NullPlaceResult("NULL_LOCATION", false);
/**
* The target world is null.
*/
public static final OperationResult NULL_WORLD = new NullPlaceResult("NULL_WORLD", false);
/**
* {@inheritDoc}
*/
private NullPlaceResult(String name, boolean isSuccessful) {
super(name, isSuccessful);
}
}
@@ -0,0 +1,32 @@
package com.onarandombox.MultiverseCore.utils.player.checkresult;
import com.onarandombox.MultiverseCore.api.operation.SimpleOperationResult;
public class PlayerLimitResult extends SimpleOperationResult {
/**
* World does not have a player limit.
*/
public static final PlayerLimitResult NO_PLAYERLIMIT = new PlayerLimitResult("NO_PLAYERLIMIT", true);
/**
* Player is within the player limit of the world.
*/
public static final PlayerLimitResult WITHIN_PLAYERLIMIT = new PlayerLimitResult("WITHIN_PLAYERLIMIT", true);
/**
* Player has permission to bypass the player limit.
*/
public static final PlayerLimitResult BYPASS_PLAYERLIMIT = new PlayerLimitResult("BYPASS_PLAYERLIMIT", true);
/**
* Player is above the player limit of the world, and cannot bypass it.
*/
public static final PlayerLimitResult EXCEED_PLAYERLIMIT = new PlayerLimitResult("EXCEED_PLAYERLIMIT", false);
/**
* {@inheritDoc}
*/
private PlayerLimitResult(String name, boolean isSuccessful) {
super(name, isSuccessful);
}
}
@@ -0,0 +1,27 @@
package com.onarandombox.MultiverseCore.utils.player.checkresult;
import com.onarandombox.MultiverseCore.api.operation.SimpleOperationResult;
public class UseDestinationResult extends SimpleOperationResult {
/**
* The result of a check if a player can use a destination.
*/
public static final UseDestinationResult CAN_USE_DESTINATION = new UseDestinationResult("CAN_USE_DESTINATION", true);
/**
* Player does not have permission to use the destination.
*/
public static final UseDestinationResult NO_DESTINATION_PERMISSION = new UseDestinationResult("NO_DESTINATION_PERMISSION", false);
/**
* Player does not have finer permission to use the destination.
*/
public static final UseDestinationResult NO_DESTINATION_PERMISSION_FINER = new UseDestinationResult("NO_DESTINATION_FINER", false);
/**
* {@inheritDoc}
*/
private UseDestinationResult(String name, boolean isSuccessful) {
super(name, isSuccessful);
}
}
@@ -0,0 +1,27 @@
package com.onarandombox.MultiverseCore.utils.player.checkresult;
import com.onarandombox.MultiverseCore.api.operation.SimpleOperationResult;
public class WorldAccessResult extends SimpleOperationResult {
/**
* Enforce world access is disabled.
*/
public static final WorldAccessResult NO_ENFORCE_WORLD_ACCESS = new WorldAccessResult("NO_ENFORCE_WORLD_ACCESS", true);
/**
* Player has permission to access world.
*/
public static final WorldAccessResult HAS_WORLD_ACCESS = new WorldAccessResult("HAS_WORLD_ACCESS", true);
/**
* Player has permission to access world access.
*/
public static final WorldAccessResult NO_WORLD_ACCESS = new WorldAccessResult("NO_WORLD_ACCESS", false);
/**
* {@inheritDoc}
*/
private WorldAccessResult(String name, boolean isSuccessful) {
super(name, isSuccessful);
}
}
@@ -0,0 +1,4 @@
/**
* This package contains the results of the {@link com.onarandombox.MultiverseCore.utils.player.PlayerActionChecker}
*/
package com.onarandombox.MultiverseCore.utils.player.checkresult;
@@ -0,0 +1,4 @@
/**
* This package contains the classes that handle the player's related utilities.
*/
package com.onarandombox.MultiverseCore.utils.player;
@@ -19,6 +19,7 @@ import com.onarandombox.MultiverseCore.api.BlockSafety;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
import com.onarandombox.MultiverseCore.utils.permission.PermissionsRegistrar;
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
import com.onarandombox.MultiverseCore.world.configuration.EnglishChatColor;
import com.onarandombox.MultiverseCore.world.configuration.SpawnLocation;
@@ -38,8 +39,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 +86,7 @@ public class SimpleMVWorld implements MVWorld {
this.props.environment = world.getEnvironment();
this.props.seed = world.getSeed();
this.initPerms();
PermissionsRegistrar.registerWorldPermissions(this);
this.props.flushChanges();
@@ -299,7 +298,7 @@ public class SimpleMVWorld implements MVWorld {
for (Player p : plugin.getServer().getWorld(getName()).getPlayers()) {
Logging.finer(String.format("Setting %s's GameMode to %s",
p.getName(), newValue.toString()));
plugin.getPlayerListener().handleGameModeAndFlight(p, SimpleMVWorld.this);
plugin.getPlayerListener().applyGameModeAndFlight(p, SimpleMVWorld.this);
}
return super.validateChange(property, newValue, oldValue, object);
}
@@ -335,11 +334,6 @@ public class SimpleMVWorld implements MVWorld {
}
}
private Permission permission;
private Permission exempt;
private Permission ignoreperm;
private Permission limitbypassperm;
/**
* Null-location.
*/
@@ -384,37 +378,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 +420,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 +661,6 @@ public class SimpleMVWorld implements MVWorld {
return this.name;
}
/**
* {@inheritDoc}
*/
@Override
public String getPermissibleName() {
return this.name.toLowerCase();
}
/**
* {@inheritDoc}
*/
@@ -912,14 +841,6 @@ public class SimpleMVWorld implements MVWorld {
return this.props.setRespawnToWorld(respawnToWorld);
}
/**
* {@inheritDoc}
*/
@Override
public Permission getAccessPermission() {
return this.permission;
}
/**
* {@inheritDoc}
*/
@@ -952,14 +873,6 @@ public class SimpleMVWorld implements MVWorld {
this.props.setPrice(price);
}
/**
* {@inheritDoc}
*/
@Override
public Permission getExemptPermission() {
return this.exempt;
}
/**
* {@inheritDoc}
*/
@@ -27,12 +27,13 @@ import java.util.stream.Collectors;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.MultiverseCoreConfiguration;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.api.WorldPurger;
import com.onarandombox.MultiverseCore.event.MVWorldDeleteEvent;
import com.onarandombox.MultiverseCore.utils.file.FileUtils;
import com.onarandombox.MultiverseCore.utils.permission.PermissionsRegistrar;
import org.bukkit.Bukkit;
import org.bukkit.GameRule;
import org.bukkit.Location;
@@ -45,8 +46,6 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.Plugin;
/**
@@ -722,29 +721,10 @@ public class SimpleMVWorldManager implements MVWorldManager {
// Basic Counter to count how many Worlds we are loading.
int count = 0;
this.ensureConfigIsPrepared();
this.ensureSecondNamespaceIsPrepared();
// 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);
PermissionsRegistrar.removeAllWorldPermissions();
this.worlds.clear();
}
@@ -764,14 +744,6 @@ public class SimpleMVWorldManager implements MVWorldManager {
this.saveWorldsConfig();
}
private void ensureSecondNamespaceIsPrepared() {
Permission special = this.plugin.getServer().getPluginManager().getPermission("mv.bypass.gamemode.*");
if (special == null) {
special = new Permission("mv.bypass.gamemode.*", PermissionDefault.FALSE);
this.plugin.getServer().getPluginManager().addPermission(special);
}
}
/**
* {@inheritDoc}
*/
@@ -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();