diff --git a/AdvancedTeleport-Bukkit/build.gradle.kts b/AdvancedTeleport-Bukkit/build.gradle.kts index 8f678b12..8fd525c8 100644 --- a/AdvancedTeleport-Bukkit/build.gradle.kts +++ b/AdvancedTeleport-Bukkit/build.gradle.kts @@ -195,6 +195,10 @@ tasks { } } +tasks.shadowJar { + from(tasks.slimJar.get().outputDirectory) +} + // Lead development use only. modrinth { token.set(System.getenv("MODRINTH_TOKEN")) @@ -467,6 +471,12 @@ bukkit { usage = "/tpofflinehere " aliases = listOf("tpofflh", "tpofflhere") } + + register("tpconfirm") { + description = "Confirms a teleportation to a dangerous zone." + permission = "at.member.confirm" + usage = "/tpconfirm" + } } permissions { diff --git a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/CoreClass.java b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/CoreClass.java index fc8679e2..423de2f2 100644 --- a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/CoreClass.java +++ b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/CoreClass.java @@ -4,6 +4,7 @@ import io.github.niestrat99.advancedteleport.config.CustomMessages; import io.github.niestrat99.advancedteleport.config.GUIConfig; import io.github.niestrat99.advancedteleport.config.MainConfig; +import io.github.niestrat99.advancedteleport.hooks.worldguard.FlagHandler; import io.github.niestrat99.advancedteleport.listeners.MapEventListeners; import io.github.niestrat99.advancedteleport.listeners.PlayerListeners; import io.github.niestrat99.advancedteleport.listeners.SignInteractListener; @@ -61,6 +62,12 @@ public void onLoad() { err.printStackTrace(); Bukkit.getPluginManager().disablePlugin(this); } + + // Wakey wakey + try { + FlagHandler.init(); + } catch (NoClassDefFoundError ignored) { + } } @Override diff --git a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/api/ATPlayer.java b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/api/ATPlayer.java index 8cd72ff0..38a77839 100644 --- a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/api/ATPlayer.java +++ b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/api/ATPlayer.java @@ -11,6 +11,7 @@ import io.github.niestrat99.advancedteleport.api.events.players.ToggleTeleportationEvent; import io.github.niestrat99.advancedteleport.config.CustomMessages; import io.github.niestrat99.advancedteleport.config.MainConfig; +import io.github.niestrat99.advancedteleport.hooks.worldguard.FlagHandler; import io.github.niestrat99.advancedteleport.managers.CooldownManager; import io.github.niestrat99.advancedteleport.managers.MovementManager; import io.github.niestrat99.advancedteleport.managers.ParticleManager; @@ -56,6 +57,7 @@ public class ATPlayer { protected @NotNull WeakReference player; protected @NotNull UUID uuid; protected @NotNull String name; + protected @Nullable Runnable confirmation; private final @NotNull PendingData> homes; private final @NotNull PendingData> blockedUsers; private final @NotNull PendingData isTeleportationEnabled; @@ -116,6 +118,7 @@ public ATPlayer( CompletableFuture.supplyAsync( () -> PlayerSQLManager.get().isTeleportationOn(uuid), CoreClass.async)); + this.confirmation = null; players.put(name.toLowerCase(), this); } @@ -149,6 +152,15 @@ public void teleport( @NotNull final ATTeleportEvent event, @NotNull final String command, @NotNull final String teleportMsg) { + this.teleport(event, command, teleportMsg, false); + } + + @ApiStatus.Internal + public void teleport( + @NotNull final ATTeleportEvent event, + @NotNull final String command, + @NotNull final String teleportMsg, + boolean confirmed) { Player player = event.getPlayer(); int warmUp = getWarmUp(command, event.getToLocation().getWorld()); if (event.isCancelled()) return; @@ -159,6 +171,17 @@ public void teleport( return; } + // If there's no confirmation, then check the area + if (!confirmed) { + try { + if (FlagHandler.isDangerous(event.getToLocation(), player)) { + requestConfirmation(() -> teleport(event, command, teleportMsg, true)); + return; + } + } catch (NoClassDefFoundError ignored) { + } + } + if (!PaymentManager.getInstance().canPay(command, player, event.getToLocation().getWorld())) return; @@ -427,6 +450,24 @@ public boolean hasBlocked(@NotNull final UUID otherPlayer) { CoreClass.async); } + @Contract(pure = true) + public boolean isAwaitingConfirmation() { + return this.confirmation != null; + } + + @Contract(pure = true) + public void requestConfirmation(@NotNull Runnable confirmed) { + this.confirmation = confirmed; + } + + @Contract(pure = true) + public void confirm() { + if (this.confirmation == null) return; + this.confirmation.run(); + this.confirmation = null; + } + + /** * Returns a hashmap of homes, where the key is the home name, and the value is the home object. * diff --git a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/commands/misc/TpConfirm.java b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/commands/misc/TpConfirm.java new file mode 100644 index 00000000..02d4560f --- /dev/null +++ b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/commands/misc/TpConfirm.java @@ -0,0 +1,39 @@ +package io.github.niestrat99.advancedteleport.commands.misc; + +import io.github.niestrat99.advancedteleport.api.ATPlayer; +import io.github.niestrat99.advancedteleport.commands.ATCommand; +import io.github.niestrat99.advancedteleport.commands.PlayerCommand; +import io.github.niestrat99.advancedteleport.config.CustomMessages; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class TpConfirm extends ATCommand implements PlayerCommand { + + @Override + public boolean getRequiredFeature() { + return true; + } + + @Override + public @NotNull String getPermission() { + return "at.member.confirm"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + + // Get the player + ATPlayer player = ATPlayer.getPlayer((Player) sender); + if (!player.isAwaitingConfirmation()) { + CustomMessages.sendMessage(sender, "Error.notAwaitingConfirmation"); + return true; + } + + // Confirm! + CustomMessages.sendMessage(sender, "Info.confirmedTeleportation"); + player.confirm(); + return true; + } +} diff --git a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/config/CustomMessages.java b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/config/CustomMessages.java index 72110137..a5c8b701 100644 --- a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/config/CustomMessages.java +++ b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/config/CustomMessages.java @@ -393,6 +393,7 @@ If you prefer to use the Legacy Code format (i.e. &a, &b, etc.) then you can sti addDefault( "Error.randomLocFailed", " Sorry, we couldn't find a location to teleport you to :("); + addDefault("Error.notAwaitingConfirmation", " You don't need to confirm any teleportation! If you're headed towards a dangerous place, we'll let you know."); makeSectionLenient("Info"); addDefault("Info.tpOff", " Successfully disabled teleport requests!"); @@ -598,6 +599,12 @@ If you prefer to use the Legacy Code format (i.e. &a, &b, etc.) then you can sti "Info.mirrorSpawnSame", " The spawns for and already to go the same place! Don't worry :)"); + addDefault( + "Info.dangerousArea", + " WARNING: the area you are teleporting to has been marked as potentially unsafe, meaning you could die or lose your items.
" + + "If you are happy to teleport to the location, please run the command /tpconfirm."); + addDefault("Info.confirmedTeleportation", " You've confirmed the teleportation! Good luck out there."); + addDefault("Tooltip.homes", " Teleports you to your home: "); addDefault("Tooltip.warps", " Teleports you to warp: "); addDefault( diff --git a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/hooks/worldguard/FlagHandler.java b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/hooks/worldguard/FlagHandler.java new file mode 100644 index 00000000..89a42285 --- /dev/null +++ b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/hooks/worldguard/FlagHandler.java @@ -0,0 +1,91 @@ +package io.github.niestrat99.advancedteleport.hooks.worldguard; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.flags.StringFlag; +import com.sk89q.worldguard.protection.flags.registry.FlagConflictException; +import com.sk89q.worldguard.protection.flags.registry.FlagRegistry; +import com.sk89q.worldguard.protection.regions.RegionContainer; +import com.sk89q.worldguard.protection.regions.RegionQuery; + +import io.github.niestrat99.advancedteleport.CoreClass; +import io.github.niestrat99.advancedteleport.config.CustomMessages; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class FlagHandler { + + private static boolean enabled = false; + public static StateFlag DANGEROUS_AREA_FLAG = null; + public static StringFlag DANGEROUS_AREA_MESSAGE = null; + + public static void init() { + final FlagRegistry registry = WorldGuard.getInstance().getFlagRegistry(); + + // Create the flags + try { + StateFlag dangerousArea = new StateFlag("dangerous-area", false); + registry.register(dangerousArea); + DANGEROUS_AREA_FLAG = dangerousArea; + + } catch (FlagConflictException ex) { + Flag flag = registry.get("dangerous-area"); + if (flag instanceof StateFlag goodFlag) { + DANGEROUS_AREA_FLAG = goodFlag; + } else { + CoreClass.getInstance().getLogger().warning( + "Another plugin has registered a conflicting dangerous-area flag! Custom WorldGuard flags for AT will not work."); + } + } + + try { + StringFlag areaMessage = new StringFlag("dangerous-area-message"); + registry.register(areaMessage); + DANGEROUS_AREA_MESSAGE = areaMessage; + } catch (FlagConflictException ex) { + Flag flag = registry.get("dangerous-area-message"); + if (flag instanceof StringFlag goodFlag) { + DANGEROUS_AREA_MESSAGE = goodFlag; + } else { + CoreClass.getInstance().getLogger().warning( + "Another plugin has registered a conflicting dangerous-area-message flag! Custom WorldGuard flags for AT will not work."); + } + } + + enabled = DANGEROUS_AREA_FLAG != null && DANGEROUS_AREA_MESSAGE != null; + } + + public static boolean isDangerous(@NotNull Location toLocation, @NotNull Player player) { + + // No WorldGuard? No problem. + if (!enabled) return false; + + // Get the region set + final RegionContainer container = + WorldGuard.getInstance().getPlatform().getRegionContainer(); + final RegionQuery query = container.createQuery(); + final ApplicableRegionSet set = query.getApplicableRegions(BukkitAdapter.adapt(toLocation)); + + // Convert the player + final LocalPlayer wgPlayer = WorldGuardPlugin.inst().wrapPlayer(player); + + // Test the region + if (!set.testState(wgPlayer, DANGEROUS_AREA_FLAG)) return false; + + // Since it's dangerous, check for the message + String message = set.queryValue(wgPlayer, DANGEROUS_AREA_MESSAGE); + if (message != null) { + CustomMessages.asAudience(player).sendMessage(CustomMessages.translate(message)); + } else { + CustomMessages.sendMessage(player, "Info.dangerousArea"); + } + return true; + } +} diff --git a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/managers/CommandManager.java b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/managers/CommandManager.java index 2c565c1e..6b37cd7e 100644 --- a/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/managers/CommandManager.java +++ b/AdvancedTeleport-Bukkit/src/main/java/io/github/niestrat99/advancedteleport/managers/CommandManager.java @@ -6,6 +6,7 @@ import io.github.niestrat99.advancedteleport.commands.SubATCommand; import io.github.niestrat99.advancedteleport.commands.core.*; import io.github.niestrat99.advancedteleport.commands.home.*; +import io.github.niestrat99.advancedteleport.commands.misc.TpConfirm; import io.github.niestrat99.advancedteleport.commands.spawn.*; import io.github.niestrat99.advancedteleport.commands.teleport.*; import io.github.niestrat99.advancedteleport.commands.warp.*; @@ -52,6 +53,8 @@ public static void registerCommands() { register("tpoffline", new TpOffline()); register("tpofflinehere", new TpHereOffline()); + register("tpconfirm", new TpConfirm()); + register("home", new HomeCommand()); register("sethome", new SetHomeCommand()); register("delhome", new DelHomeCommand()); diff --git a/README.md b/README.md index ba3dc803..d8baeec3 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ Advanced Teleport is a rapidly growing plugin that is not only increasing sharpl ## Installation/Cloning As of currently, Advanced Teleport uses Gradle to manage its dependencies. -The Gradle command used to build the plugin is `gradle shadowJar` and is done under the AdvancedTeleport-Bukkit module. +The Gradle command used to build the plugin is `gradle slimJar` and is done under the AdvancedTeleport-Bukkit module. + +> NOTE: Due to a bug with SlimJar you should try building twice when updating dependencies or building for the first time, or necessary files will not be installed.