diff --git a/src/main/java/com/ncguy/usefulskyblock/Reference.java b/src/main/java/com/ncguy/usefulskyblock/Reference.java index 8c59dfd..8de3dd3 100644 --- a/src/main/java/com/ncguy/usefulskyblock/Reference.java +++ b/src/main/java/com/ncguy/usefulskyblock/Reference.java @@ -4,6 +4,7 @@ import com.ncguy.usefulskyblock.pdc.AnonymousDataContainerRef; import com.ncguy.usefulskyblock.pdc.IDataContainerRef; import com.ncguy.usefulskyblock.pdc.VectorPersistentDataType; import io.papermc.paper.datacomponent.DataComponentType; +import net.kyori.adventure.key.Key; import org.bukkit.NamespacedKey; import org.bukkit.World; import org.bukkit.block.Block; @@ -21,6 +22,9 @@ public class Reference { return new NamespacedKey("usefulskyblock", key); } + public static Key DIALOG_AGREE = key("dialog/agree"); + public static Key DIALOG_DISAGREE = key("dialog/disagree"); + public static IDataContainerRef SKYBLOCK_TEAM_ROOT = new AnonymousDataContainerRef<>(key("world.skyblock.team"), VectorPersistentDataType.Instance); public static IDataContainerRef SKYBLOCK_TEAM_COUNT = SKYBLOCK_TEAM_ROOT.withSuffix(".count").withType(PersistentDataType.INTEGER); public static IDataContainerRef WORLD_INIT = new AnonymousDataContainerRef<>(key("world.init"), PersistentDataType.BOOLEAN); diff --git a/src/main/java/com/ncguy/usefulskyblock/UsefulSkyblock.java b/src/main/java/com/ncguy/usefulskyblock/UsefulSkyblock.java index 4aa02be..1be852a 100644 --- a/src/main/java/com/ncguy/usefulskyblock/UsefulSkyblock.java +++ b/src/main/java/com/ncguy/usefulskyblock/UsefulSkyblock.java @@ -6,7 +6,22 @@ import com.ncguy.usefulskyblock.recipe.BiomeRod; import com.ncguy.usefulskyblock.recipe.IRecipeProvider; import com.ncguy.usefulskyblock.recipe.SmeltingCraftingHandler; import com.ncguy.usefulskyblock.world.PortalHandler; +import io.papermc.paper.connection.PlayerCommonConnection; +import io.papermc.paper.dialog.Dialog; +import io.papermc.paper.event.player.PlayerCustomClickEvent; +import io.papermc.paper.registry.RegistryBuilderFactory; +import io.papermc.paper.registry.data.dialog.ActionButton; +import io.papermc.paper.registry.data.dialog.DialogBase; +import io.papermc.paper.registry.data.dialog.DialogRegistryEntry; +import io.papermc.paper.registry.data.dialog.action.DialogAction; +import io.papermc.paper.registry.data.dialog.type.DialogType; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.*; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.inventory.Recipe; import org.bukkit.plugin.PluginManager; @@ -15,11 +30,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; public final class UsefulSkyblock extends JavaPlugin implements Listener { private static final Logger log = LoggerFactory.getLogger(UsefulSkyblock.class); + public UsefulSkyblock() { + dialogMaps = new java.util.concurrent.ConcurrentHashMap<>(); + } + @Override public void onEnable() { saveDefaultConfig(); @@ -69,4 +91,43 @@ public final class UsefulSkyblock extends JavaPlugin implements Listener { // Plugin shutdown logic } + private final Map> dialogMaps; + + @EventHandler + void onHandleDialog(PlayerCustomClickEvent event) { + Key key = event.getIdentifier(); + CompletableFuture f = dialogMaps.get(event.getCommonConnection()); + Boolean res = null; + if(key.equals(Reference.DIALOG_AGREE)) + res = true; + else if(key.equals(Reference.DIALOG_DISAGREE)) + res = false; + + if(res != null && f != null) { + f.complete(res); + dialogMaps.remove(event.getCommonConnection()); + } + } + + public CompletableFuture confirm(Player player, Component base, Consumer builder) { + + var confirmBtn = ActionButton.builder(Component.text("Confirm", NamedTextColor.GREEN)).tooltip(Component.text("Click to confirm")).action(DialogAction.customClick(Reference.DIALOG_AGREE, null)).build(); + var cancelBtn = ActionButton.builder(Component.text("Cancel", NamedTextColor.RED)).tooltip(Component.text("Click to cancel")).action(DialogAction.customClick(Reference.DIALOG_DISAGREE, null)).build(); + + Dialog dialog = Dialog.create(innerBuilder -> { + DialogBase.Builder baseBuilder = DialogBase.builder(base); + baseBuilder.canCloseWithEscape(false); + builder.accept(baseBuilder); + innerBuilder.empty() + .base(baseBuilder.build()) + .type(DialogType.confirmation(confirmBtn, cancelBtn)); + }); + + player.showDialog(dialog); + + CompletableFuture f = new CompletableFuture<>(); + dialogMaps.put(player.getConnection(), f); + return f; + } + } diff --git a/src/main/java/com/ncguy/usefulskyblock/command/SkyblockGenCommand.java b/src/main/java/com/ncguy/usefulskyblock/command/SkyblockGenCommand.java index 35ea627..74e6e9f 100644 --- a/src/main/java/com/ncguy/usefulskyblock/command/SkyblockGenCommand.java +++ b/src/main/java/com/ncguy/usefulskyblock/command/SkyblockGenCommand.java @@ -8,15 +8,14 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.mojang.brigadier.tree.LiteralCommandNode; -import com.ncguy.usefulskyblock.Advancements; -import com.ncguy.usefulskyblock.IslandNetworkGenerator; -import com.ncguy.usefulskyblock.Reference; -import com.ncguy.usefulskyblock.StructureRef; +import com.ncguy.usefulskyblock.*; import com.ncguy.usefulskyblock.data.BiomedStructure; +import com.ncguy.usefulskyblock.utils.Components; import com.ncguy.usefulskyblock.utils.TextUtils; import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.Commands; import io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import io.papermc.paper.registry.data.dialog.body.DialogBody; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextColor; @@ -30,6 +29,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.PlayerInventory; +import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.ScoreboardManager; import org.bukkit.scoreboard.Team; @@ -37,11 +37,9 @@ import org.bukkit.util.BlockVector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Arrays; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; import static com.ncguy.usefulskyblock.Reference.key; @@ -226,18 +224,42 @@ public class SkyblockGenCommand extends AbstractSkyblockCommand { var islandHomeLoc = Reference.ISLAND_HOME_LOC.assign(player); World overworld = getServer().getWorld(new NamespacedKey("minecraft", "overworld")); - if (islandHomeLoc.has()) { - - if (!isInventoryEmpty(confirmationGiven, executor, player)) - return -1; - + Runnable doTeleport = () -> { + executor.sendMessage("Teleported to island home.."); BlockVector blockVector = islandHomeLoc.get(); Location loc = new Location(overworld, blockVector.getX(), blockVector.getY(), blockVector.getZ()); if (!player.teleport(loc, PlayerTeleportEvent.TeleportCause.COMMAND)) { player.sendMessage("Failed to teleport you to your island home, please notify an administrator"); - return -1; + return; } player.getInventory().clear(); + if(player.getGameMode() != GameMode.SURVIVAL) + player.setGameMode(GameMode.SURVIVAL); + }; + + Runnable tryTeleport = () -> { + if (!isInventoryEmpty(confirmationGiven, executor, player)) { + JavaPlugin.getPlugin(UsefulSkyblock.class) + .confirm(player, Component.text("Teleporting to an island will clear your inventory"), b -> { + b.body(List.of( + DialogBody.plainMessage(Component.text("Know that this action is irreversible")), + DialogBody.plainMessage(Component.newline()), + DialogBody.plainMessage(Component.text("To skip this notice in future, use the command variant ").append(Components.Command("/skyblock confirm")).append(Component.text("."))) + )); + }).thenAccept(res -> { + if (res) { + doTeleport.run(); + } else { + player.sendMessage("Teleport cancelled"); + } + }); + return; + } + + doTeleport.run(); + + if (islandHomeLoc.has()) { + tryTeleport.run(); return 0; } @@ -255,19 +277,8 @@ public class SkyblockGenCommand extends AbstractSkyblockCommand { String sanitizedTeamName = playerTeamName.replaceAll("[^a-z0-9_.]", "_"); var teamSpawn = Reference.SKYBLOCK_TEAM_ROOT.withSuffix("." + sanitizedTeamName).assign(overworld); if (teamSpawn.has()) { - - if (!isInventoryEmpty(confirmationGiven, executor, player)) - return -1; - islandHomeLoc.set(teamSpawn.get()); - executor.sendMessage("Teleported to island home.."); - BlockVector blockVector = islandHomeLoc.get(); - Location loc = new Location(overworld, blockVector.getX(), blockVector.getY(), blockVector.getZ()); - if (!player.teleport(loc, PlayerTeleportEvent.TeleportCause.COMMAND)) { - player.sendMessage("Failed to teleport you to your island home, please notify an administrator"); - return -1; - } - player.getInventory().clear(); + tryTeleport.run(); return 0; } @@ -284,10 +295,11 @@ public class SkyblockGenCommand extends AbstractSkyblockCommand { boolean hasItemInOffhand = inventory.getItemInOffHand().getType() != Material.AIR; boolean hasItemInInventory = Arrays.stream(inventory.getContents()).anyMatch(Objects::nonNull); - if(hasArmour || hasItemInOffhand || hasItemInInventory) { - if(!confirmationGiven) { + if (hasArmour || hasItemInOffhand || hasItemInInventory) { + if (!confirmationGiven) { executor.sendMessage(Component.text("You have items in your inventory, teleporting you to your island will remove them.")); - executor.sendMessage(Component.text("If you wish to keep your items, please confirm via the command ").append(Component.text("/skyblock confirm", Style.style(TextColor.color(0x00, 0xff, 0xff))))); + executor.sendMessage(Component.text("If you wish to keep your items, please confirm via the command ") + .append(Component.text("/skyblock confirm", Style.style(TextColor.color(0x00, 0xff, 0xff))))); return false; } } diff --git a/src/main/java/com/ncguy/usefulskyblock/utils/Components.java b/src/main/java/com/ncguy/usefulskyblock/utils/Components.java new file mode 100644 index 0000000..29f0032 --- /dev/null +++ b/src/main/java/com/ncguy/usefulskyblock/utils/Components.java @@ -0,0 +1,13 @@ +package com.ncguy.usefulskyblock.utils; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; + +public class Components { + + public static Component Command(String command) { + return Component.text(command, Style.style(TextColor.color(0x00, 0xff, 0xff))); + } + +}