Compare commits

..
Author SHA1 Message Date
Ben Woo fee9b95bef Safer null checking with parsing enum value. 2021-07-22 11:42:54 +08:00
Ben Woo b940063104 Implement new way of mapping enums with alias. 2021-07-22 11:39:39 +08:00
10 changed files with 201 additions and 130 deletions

No files matched your search

@@ -337,8 +337,7 @@ public class MVWorld implements MultiverseWorld {
private Permission permission;
private Permission exempt;
private Permission ignoregamemodeperm;
private Permission ignoreflyperm;
private Permission ignoreperm;
private Permission limitbypassperm;
/**
@@ -391,10 +390,8 @@ public class MVWorld implements MultiverseWorld {
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.ignoregamemodeperm = new Permission("mv.bypass.gamemode." + this.getName(),
this.ignoreperm = new Permission("mv.bypass.gamemode." + this.getName(),
"Allows players with this permission to ignore gamemode changes.", PermissionDefault.FALSE);
this.ignoreflyperm = new Permission("mv.bypass.fly." + this.getName(),
"Allows players with this permission to ignore fly 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);
@@ -404,15 +401,13 @@ public class MVWorld implements MultiverseWorld {
try {
this.plugin.getServer().getPluginManager().addPermission(this.permission);
this.plugin.getServer().getPluginManager().addPermission(this.exempt);
this.plugin.getServer().getPluginManager().addPermission(this.ignoregamemodeperm);
this.plugin.getServer().getPluginManager().addPermission(this.ignoreflyperm);
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.ignoregamemodeperm.addParent("mv.bypass.gamemode.*", true);
this.ignoreflyperm.addParent("mv.bypass.fly.*", true);
this.ignoreperm.addParent("mv.bypass.gamemode.*", true);
// Add limit bypass to it's parent
this.limitbypassperm.addParent("mv.bypass.playerlimit.*", true);
} catch (IllegalArgumentException e) {
@@ -9,6 +9,7 @@ package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.enums.MVEnums;
import com.pneumaticraft.commandhandler.CommandHandler;
import org.bukkit.ChatColor;
import org.bukkit.World.Environment;
@@ -21,6 +22,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/**
* Creates a new world and loads it.
@@ -90,23 +92,22 @@ public class CreateCommand extends MultiverseCommand {
return;
}
Environment environment = EnvironmentCommand.getEnvFromString(env);
if (environment == null) {
// Parse Environment.
Optional<Environment> environment = MVEnums.ENVIRONMENT.parseValue(env);
if (!environment.isPresent()) {
sender.sendMessage(ChatColor.RED + "That is not a valid environment.");
EnvironmentCommand.showEnvironments(sender);
return;
}
// If they didn't specify a type, default to NORMAL
if (typeString == null) {
typeString = "NORMAL";
}
WorldType type = EnvironmentCommand.getWorldTypeFromString(typeString);
if (type == null) {
// Parse WorldType. If they didn't specify a type, default to normal.
Optional<WorldType> type = MVEnums.WORLD_TYPE.parseValue(typeString == null ? "normal" : typeString);
if (!type.isPresent()) {
sender.sendMessage(ChatColor.RED + "That is not a valid World Type.");
EnvironmentCommand.showWorldTypes(sender);
return;
}
// Determine if the generator is valid. #918
if (generator != null) {
List<String> genarray = new ArrayList<String>(Arrays.asList(generator.split(":")));
@@ -122,7 +123,13 @@ public class CreateCommand extends MultiverseCommand {
}
Command.broadcastCommandMessage(sender, "Starting creation of world '" + worldName + "'...");
if (this.worldManager.addWorld(worldName, environment, seed, type, allowStructures, generator, useSpawnAdjust)) {
if (this.worldManager.addWorld(
worldName,
environment.get(),
seed, type.get(),
allowStructures,
generator,
useSpawnAdjust)) {
Command.broadcastCommandMessage(sender, "Complete!");
} else {
Command.broadcastCommandMessage(sender, "FAILED.");
@@ -8,6 +8,7 @@
package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.enums.MVEnums;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.WorldType;
@@ -68,25 +69,11 @@ public class EnvironmentCommand extends MultiverseCommand {
*
* @param type The WorldType as a {@link String}
* @return The WorldType as a {@link WorldType}
* @deprecated Use {@link MVEnums#WORLD_TYPE} instead.
*/
@Deprecated
public static WorldType getWorldTypeFromString(String type) {
// Don't reference the enum directly as there aren't that many, and we can be more forgiving to users this way
if (type.equalsIgnoreCase("normal")) {
type = "NORMAL";
} else if (type.equalsIgnoreCase("flat")) {
type = "FLAT";
} else if (type.equalsIgnoreCase("largebiomes")) {
type = "LARGE_BIOMES";
} else if (type.equalsIgnoreCase("amplified")) {
type = "AMPLIFIED";
}
try {
// Now that we've converted a potentially unfriendly value
// to a friendly one, get it from the ENUM!
return WorldType.valueOf(type);
} catch (IllegalArgumentException e) {
return null;
}
return MVEnums.WORLD_TYPE.parseValue(type).orElse(null);
}
/**
@@ -94,25 +81,10 @@ public class EnvironmentCommand extends MultiverseCommand {
*
* @param env The environment as {@link String}
* @return The environment as {@link org.bukkit.World.Environment}
* @deprecated Use {@link MVEnums#ENVIRONMENT} instead.
*/
@Deprecated
public static World.Environment getEnvFromString(String env) {
env = env.toUpperCase();
// Don't reference the enum directly as there aren't that many, and we can be more forgiving to users this way
if (env.equalsIgnoreCase("HELL") || env.equalsIgnoreCase("NETHER"))
env = "NETHER";
if (env.equalsIgnoreCase("END") || env.equalsIgnoreCase("THEEND") || env.equalsIgnoreCase("STARWARS"))
env = "THE_END";
if (env.equalsIgnoreCase("NORMAL") || env.equalsIgnoreCase("WORLD"))
env = "NORMAL";
try {
// Now that we've converted a potentially unfriendly value
// to a friendly one, get it from the ENUM!
return World.Environment.valueOf(env);
} catch (IllegalArgumentException e) {
return null;
}
return MVEnums.ENVIRONMENT.parseValue(env).orElse(null);
}
}
@@ -9,6 +9,7 @@ package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.enums.MVEnums;
import com.onarandombox.MultiverseCore.utils.WorldNameChecker;
import com.pneumaticraft.commandhandler.CommandHandler;
import org.bukkit.ChatColor;
@@ -20,6 +21,7 @@ import org.bukkit.permissions.PermissionDefault;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
/**
* Imports a new world of the specified type.
@@ -106,8 +108,8 @@ public class ImportCommand extends MultiverseCommand {
}
String env = args.get(1);
Environment environment = EnvironmentCommand.getEnvFromString(env);
if (environment == null) {
Optional<Environment> environment = MVEnums.ENVIRONMENT.parseValue(env);
if (!environment.isPresent()) {
sender.sendMessage(ChatColor.RED + "That is not a valid environment.");
EnvironmentCommand.showEnvironments(sender);
return;
@@ -128,10 +130,18 @@ public class ImportCommand extends MultiverseCommand {
sender.sendMessage("For a list of available world types, type: " + ChatColor.AQUA + "/mvenv");
} else {
Command.broadcastCommandMessage(sender, String.format("Starting import of world '%s'...", worldName));
if (this.worldManager.addWorld(worldName, environment, null, null, null, generator, useSpawnAdjust))
if (this.worldManager.addWorld(worldName,
environment.get(),
null,
null,
null,
generator,
useSpawnAdjust)) {
Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Complete!");
else
}
else {
Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed!");
}
}
}
}
@@ -0,0 +1,20 @@
package com.onarandombox.MultiverseCore.enums;
import com.onarandombox.MultiverseCore.utils.EnumMapping;
import org.bukkit.World;
import org.bukkit.WorldType;
public class MVEnums {
public static final EnumMapping<World.Environment> ENVIRONMENT = EnumMapping.builder(World.Environment.class)
.addAlias("overworld", World.Environment.NORMAL)
.addAlias("hell", World.Environment.NETHER)
.addAlias("end", World.Environment.THE_END)
.addAlias("starwars", World.Environment.THE_END)
.mapWithoutUnderscore()
.build();
public static final EnumMapping<WorldType> WORLD_TYPE = EnumMapping.builder(WorldType.class)
.mapWithoutUnderscore()
.build();
}
@@ -349,42 +349,36 @@ public class MVPlayerListener implements Listener {
// 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 (player.getWorld() != world.getCBWorld()) {
Logging.fine("The gamemode 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;
}
boolean isAllowFlight = player.getAllowFlight();
boolean isFlying = player.isFlying();
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.
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());
} else {
Logging.fine("Player: " + player.getName() + " is IMMUNE to gamemode changes!");
}
if (!MVPlayerListener.this.pt.playerCanIgnoreFlyRestriction(world, player)) {
if (player.getGameMode() == GameMode.CREATIVE && world.getAllowFlight()) {
player.setAllowFlight(true);
} else if (isAllowFlight && player.getGameMode() != GameMode.SPECTATOR) {
player.setAllowFlight(false);
player.setFlying(false);
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!");
}
} else {
// Set back to previous state before gamemode change
player.setAllowFlight(isAllowFlight);
player.setFlying(isFlying);
Logging.fine("Player: " + player.getName() + " is IMMUNE to fly changes!");
}
}
}, 1L);
}, 1L);
}
}
@@ -0,0 +1,107 @@
package com.onarandombox.MultiverseCore.utils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class EnumMapping<T extends Enum<T>> {
public static <T extends Enum<T>> Builder<T> builder(Class<T> enumClass) {
return builder(enumClass, false);
}
public static <T extends Enum<T>> Builder<T> builder(Class<T> enumClass, boolean caseSensitive) {
return new Builder<>(enumClass, caseSensitive);
}
private final Class<T> enumClass;
private final boolean caseSensitive;
private final Map<String, T> enumsMap;
public EnumMapping(Class<T> enumClass, boolean caseSensitive) {
this.enumClass = enumClass;
this.caseSensitive = caseSensitive;
this.enumsMap = new HashMap<>();
}
@NotNull
public Optional<T> parseValue(@Nullable String value) {
if (value == null) {
return Optional.empty();
}
T enumType = this.enumsMap.get(caseSensitive ? value : value.toLowerCase());
if (enumType != null) {
return Optional.of(enumType);
}
try {
return Optional.of(Enum.valueOf(enumClass, value));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
@NotNull
public Map<String, T> getEnumsMap() {
return Collections.unmodifiableMap(this.enumsMap);
}
public boolean isCaseSensitive() {
return caseSensitive;
}
public Class<? extends Enum<T>> getEnumClass() {
return enumClass;
}
public static class Builder<T extends Enum<T>> {
private final EnumMapping<T> enumMapping;
public Builder(Class<T> enumClass, boolean caseSensitive) {
this.enumMapping = new EnumMapping<>(enumClass, caseSensitive);
if (!this.enumMapping.caseSensitive) {
addLowerCaseMap();
}
}
private void addLowerCaseMap() {
Arrays.stream(this.enumMapping.enumClass.getEnumConstants()).forEach(enumType -> {
addAlias(enumType.name(), enumType);
});
}
public Builder<T> mapWithoutUnderscore() {
Arrays.stream(this.enumMapping.enumClass.getEnumConstants()).forEach(enumType -> {
addAlias(enumType.name().replace("_", ""), enumType);
});
return this;
}
@NotNull
public Builder<T> addAlias(String aliasName, String enumString) {
this.enumMapping.parseValue(enumString).ifPresent(enumType -> addAlias(aliasName, enumType));
return this;
}
@NotNull
public Builder<T> addAlias(String aliasName, T enumType) {
if (!this.enumMapping.caseSensitive) {
aliasName = aliasName.toLowerCase();
}
this.enumMapping.enumsMap.computeIfAbsent(aliasName, name -> enumType);
return this;
}
@NotNull
public EnumMapping<T> build() {
return this.enumMapping;
}
}
}
@@ -48,17 +48,6 @@ public class MVPermissions implements PermissionsInterface {
return p.hasPermission("mv.bypass.gamemode." + w.getName());
}
/**
* Check if a Player can ignore Fly restrictions for world they travel to.
*
* @param p The {@link Player} to check.
* @param w The {@link MultiverseWorld} the player wants to teleport to.
* @return True if they should bypass restrictions.
*/
public boolean canIgnoreFlyRestriction(Player p, MultiverseWorld w) {
return p.hasPermission("mv.bypass.fly." + w.getName());
}
/**
* Check if a Player can teleport to the Destination world from there current world.
*
@@ -300,21 +300,4 @@ public class PermissionTools {
return true;
}
}
/**
* Checks to see if a player should bypass fly restrictions.
*
* @param toWorld world travelling to.
* @param teleportee player travelling.
* @return True if they should bypass restrictions
*/
public boolean playerCanIgnoreFlyRestriction(MultiverseWorld toWorld, Player teleportee) {
if (toWorld != null) {
return this.plugin.getMVPerms().canIgnoreFlyRestriction(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;
}
}
}
@@ -753,7 +753,6 @@ public class WorldManager implements MVWorldManager {
this.plugin.getServer().getPluginManager().removePermission(w.getExemptPermission().getName());
// Special namespace for gamemodes
this.plugin.getServer().getPluginManager().removePermission("mv.bypass.gamemode." + w.getName());
this.plugin.getServer().getPluginManager().removePermission("mv.bypass.fly." + w.getName());
}
// Recalc the all permission
this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(allAccess);
@@ -778,15 +777,10 @@ public class WorldManager implements MVWorldManager {
}
private void ensureSecondNamespaceIsPrepared() {
Permission specialGameMode = this.plugin.getServer().getPluginManager().getPermission("mv.bypass.gamemode.*");
Permission specialFly = this.plugin.getServer().getPluginManager().getPermission("mv.bypass.fly.*");
if (specialGameMode == null) {
specialGameMode = new Permission("mv.bypass.gamemode.*", PermissionDefault.FALSE);
this.plugin.getServer().getPluginManager().addPermission(specialGameMode);
}
if (specialFly == null) {
specialFly = new Permission("mv.bypass.fly.*", PermissionDefault.FALSE);
this.plugin.getServer().getPluginManager().addPermission(specialFly);
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);
}
}