diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c0ec401 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,17 @@ +# CHANGELOG + +## [3.2.0] - 06-07-2025 +- Added trident manager, tridents will return to player if despawned. +- MessageBuilder now has a `nomessage` key that returns early. +- UpdateUtil will no longer send a message on join if the message is "nomessage" or " ". +- SpawnCommand is now a TabExecutor (todo: make /spawn %player%). +- Added `hubbly.command.debug` permission +- /spawn can now be configured to teleport after a few seconds +- Added `spawn.timer` in config +- Added `teleporting` and `teleport_cancelled` keys in en.yml +- Added `/hubbly worlds list` command +- OPs no longer always bypass `cancel_events` (you can deny them the permission) +- Fix `/hubbly worlds` `remove` and `check` subcommands +- `/hubbly worlds` `add` and `remove` now reflect in config +- LockChat now properly sends Locale message +- Added Portuguese language (Thank you snowy727. on discord) \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 0d338ee..719346f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -48,7 +48,7 @@ dependencies { } group = "me.calrl" -version = "3.1.1" +version = "3.2.0" description = "Hubbly" java.sourceCompatibility = JavaVersion.VERSION_21 diff --git a/src/main/java/me/calrl/hubbly/Hubbly.java b/src/main/java/me/calrl/hubbly/Hubbly.java index 2215413..fed5cee 100644 --- a/src/main/java/me/calrl/hubbly/Hubbly.java +++ b/src/main/java/me/calrl/hubbly/Hubbly.java @@ -74,6 +74,7 @@ public class Hubbly extends JavaPlugin { private SubCommandManager subCommandManager; private HookManager hookManager; private ManagerFactory managerFactory; + private boolean isLoaded; public final NamespacedKey FLY_KEY = new NamespacedKey(this, "hubbly.canfly"); private String prefix; @@ -145,9 +146,10 @@ private void loadListeners() { registerListener(new PlayerJoinListener(this)); registerListener(new CommandBlockerListener(this)); registerListener(new ForceinvListener(this), "player.forceinventory"); - registerListener(new ChatListener(this), "blocked_words.enabled"); + registerListener(new ChatListener(this)); registerListener(new InventoryListener(this)); registerListener(new XPListener(this), "player.experience.enabled"); + registerListener(new PlayerMoveListener(this)); } @Override @@ -210,6 +212,7 @@ public void onEnable() { } logger.info("Hubbly has been enabled!"); + this.isLoaded = true; } @Override @@ -324,7 +327,9 @@ public void setHookManager(HookManager hookManager) { this.hookManager = hookManager; } public ManagerFactory getManagerFactory() { return this.managerFactory; } - + public static void setInstance(Hubbly hubbly) { + instance = hubbly; + } public static void enableTestMode() { testMode = true; @@ -334,4 +339,12 @@ public static boolean isTestMode() { return testMode; } + public boolean isLoaded() { + return isLoaded; + } + + public void setLoaded(boolean loaded) { + isLoaded = loaded; + } + } diff --git a/src/main/java/me/calrl/hubbly/commands/LockChatCommand.java b/src/main/java/me/calrl/hubbly/commands/LockChatCommand.java index d4d9fc1..218a047 100644 --- a/src/main/java/me/calrl/hubbly/commands/LockChatCommand.java +++ b/src/main/java/me/calrl/hubbly/commands/LockChatCommand.java @@ -42,21 +42,24 @@ public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command lockChat = plugin.getLockChat(); String key; if(lockChat.getChatLock()) { - key = "messages.chat_unlocked"; - String message = plugin.getConfig().getString("messages.chat_unlocked", "Chat has been unlocked by:"); + key = "chat_unlocked"; + String message = plugin.getConfig().getString(key, "Chat has been unlocked by:"); if(message.contains("%player%")) { message = message.replace("%player%", commandSender.getName()); } } else { - key = "messages.chat_locked"; - String message = plugin.getConfig().getString("messages.chat_locked", "Chat has been locked by:"); + key = "chat_locked"; + String message = plugin.getConfig().getString(key, "Chat has been locked by:"); if(message.contains("%player%")) { message = message.replace("%player%", commandSender.getName()); } } DisabledWorlds disabledWorlds = plugin.getDisabledWorldsManager(); MessageBuilder builder = new MessageBuilder(plugin) - .setKey(key); + .setPlayer(commandSender) + .setKey(key) + .replace("%player_name%", commandSender.getName()); + for(Player p : Bukkit.getOnlinePlayers()) { if(disabledWorlds.inDisabledWorld(p.getWorld())) { diff --git a/src/main/java/me/calrl/hubbly/commands/SpawnCommand.java b/src/main/java/me/calrl/hubbly/commands/SpawnCommand.java index ba118b7..5962cae 100644 --- a/src/main/java/me/calrl/hubbly/commands/SpawnCommand.java +++ b/src/main/java/me/calrl/hubbly/commands/SpawnCommand.java @@ -18,24 +18,28 @@ package me.calrl.hubbly.commands; import me.calrl.hubbly.Hubbly; -import me.calrl.hubbly.enums.LocaleKey; import me.calrl.hubbly.events.HubblySpawnEvent; import me.calrl.hubbly.interfaces.CustomItem; +import me.calrl.hubbly.managers.SpawnTaskManager; +import me.calrl.hubbly.tasks.spawn.SpawnTeleportTask; import me.calrl.hubbly.utils.MessageBuilder; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; -public class SpawnCommand implements CommandExecutor { +public class SpawnCommand implements TabExecutor { private final Hubbly plugin; private FileConfiguration config; @@ -46,12 +50,15 @@ public SpawnCommand(Hubbly plugin) { } @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) { + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { config = plugin.getConfig(); + + if(!(sender instanceof Player player)) { sender.sendMessage(ChatColor.RED + config.getString("messages.no_console")); return true; } + Location spawn = plugin.getUtils().getSpawn(); HubblySpawnEvent event = new HubblySpawnEvent(player, spawn); Bukkit.getPluginManager().callEvent(event); @@ -64,13 +71,22 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command return true; } - if(!event.isCancelled()) { - Bukkit.getScheduler().runTaskLater(plugin, ()-> { - player.teleport(spawn); - }, 1L); + if(!event.isCancelled()) { + long timer = plugin.getConfig().getLong("spawn.timer"); + SpawnTaskManager manager = plugin.getManagerFactory().getSpawnTaskManager(); + new SpawnTeleportTask(plugin, player, timer).start(); } return true; } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) { + if (!(sender instanceof Player player)) return null; + + final List completions = new ArrayList<>(); + + return completions; + } } \ No newline at end of file diff --git a/src/main/java/me/calrl/hubbly/commands/subcommands/worlds/WorldsCommand.java b/src/main/java/me/calrl/hubbly/commands/debug/DebugCommand.java similarity index 57% rename from src/main/java/me/calrl/hubbly/commands/subcommands/worlds/WorldsCommand.java rename to src/main/java/me/calrl/hubbly/commands/debug/DebugCommand.java index 590968c..4030c51 100644 --- a/src/main/java/me/calrl/hubbly/commands/subcommands/worlds/WorldsCommand.java +++ b/src/main/java/me/calrl/hubbly/commands/debug/DebugCommand.java @@ -1,56 +1,51 @@ -package me.calrl.hubbly.commands.subcommands.worlds; +package me.calrl.hubbly.commands.debug; import me.calrl.hubbly.Hubbly; import me.calrl.hubbly.enums.Permissions; -import me.calrl.hubbly.interfaces.SubCommand; +import me.calrl.hubbly.enums.Result; import me.calrl.hubbly.utils.CommandNode; import me.calrl.hubbly.utils.MessageBuilder; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import java.util.*; - -public class WorldsCommand extends CommandNode { +import java.util.List; +public class DebugCommand extends CommandNode { private Hubbly plugin; - public WorldsCommand(Hubbly plugin) { - super("worlds"); + public DebugCommand(Hubbly plugin) { + super("debug"); this.plugin = plugin; this.loadNodes(); } - private void loadNodes() { - addChild("add", new AddCommand(plugin)); - addChild("remove", new RemoveCommand(plugin)); - addChild("check", new CheckCommand(plugin)); - } - @Override - public void execute(CommandSender sender, String[] args, int depth) { - if(!sender.hasPermission(Permissions.COMMAND_WORLDS.getPermission())) { + public Result execute(CommandSender sender, String[] args, int depth) { + if(!sender.hasPermission(Permissions.COMMAND_DEBUG.getPermission())) { new MessageBuilder(plugin).setKey("no_permission_command").setPlayer(sender).send(); - return; + return Result.NO_PERMISSION; } if (args.length > depth) { CommandNode child = children.get(args[depth].toLowerCase()); if (child != null) { child.execute(sender, args, depth + 1); - return; + return Result.SUCCESS; } } new MessageBuilder(plugin) - .setKey("subcommands.worlds.usage") + .setKey("subcommands.debug.usage") .setPlayer(sender) .send(); + return Result.USAGE_PRINTED; + } + + private void loadNodes() { + } @Override public List tabComplete(CommandSender sender, String[] args, int depth) { return super.tabComplete(sender, args, depth); } - } diff --git a/src/main/java/me/calrl/hubbly/commands/subcommands/worlds/AddCommand.java b/src/main/java/me/calrl/hubbly/commands/worlds/AddWorldCommand.java similarity index 81% rename from src/main/java/me/calrl/hubbly/commands/subcommands/worlds/AddCommand.java rename to src/main/java/me/calrl/hubbly/commands/worlds/AddWorldCommand.java index cd93608..fc476f1 100644 --- a/src/main/java/me/calrl/hubbly/commands/subcommands/worlds/AddCommand.java +++ b/src/main/java/me/calrl/hubbly/commands/worlds/AddWorldCommand.java @@ -1,36 +1,34 @@ -package me.calrl.hubbly.commands.subcommands.worlds; +package me.calrl.hubbly.commands.worlds; import me.calrl.hubbly.Hubbly; import me.calrl.hubbly.enums.Permissions; -import me.calrl.hubbly.interfaces.SubCommand; +import me.calrl.hubbly.enums.Result; import me.calrl.hubbly.utils.CommandNode; import me.calrl.hubbly.utils.MessageBuilder; import org.bukkit.Bukkit; import org.bukkit.World; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import java.util.Collections; import java.util.List; -public class AddCommand extends CommandNode { +public class AddWorldCommand extends CommandNode { private Hubbly plugin; - public AddCommand(Hubbly plugin) { + public AddWorldCommand(Hubbly plugin) { super("add"); this.plugin = plugin; } @Override - public void execute(CommandSender sender, String[] args, int depth) { + public Result execute(CommandSender sender, String[] args, int depth) { if(!sender.hasPermission(Permissions.COMMAND_WORLDS_ADD.getPermission())) { new MessageBuilder(plugin).setKey("no_permission_command").setPlayer(sender).send(); - return; + return Result.NO_PERMISSION; } if(args.length <= depth) { new MessageBuilder(plugin).setKey("subcommands.worlds.add.usage").setPlayer(sender).send(); - return; + return Result.USAGE_PRINTED; } String worldName = args[depth]; @@ -41,7 +39,7 @@ public void execute(CommandSender sender, String[] args, int depth) { .setPlayer(sender) .replace("%world%", worldName) .send(); - return; + return Result.FAILURE; } plugin.getDisabledWorldsManager().addWorld(world); @@ -51,6 +49,7 @@ public void execute(CommandSender sender, String[] args, int depth) { .setPlayer(sender) .replace("%world%", world.getName()) .send(); + return Result.SUCCESS; } @Override diff --git a/src/main/java/me/calrl/hubbly/commands/subcommands/worlds/CheckCommand.java b/src/main/java/me/calrl/hubbly/commands/worlds/CheckWorldCommand.java similarity index 81% rename from src/main/java/me/calrl/hubbly/commands/subcommands/worlds/CheckCommand.java rename to src/main/java/me/calrl/hubbly/commands/worlds/CheckWorldCommand.java index 887dc88..9ccd1d2 100644 --- a/src/main/java/me/calrl/hubbly/commands/subcommands/worlds/CheckCommand.java +++ b/src/main/java/me/calrl/hubbly/commands/worlds/CheckWorldCommand.java @@ -1,36 +1,34 @@ -package me.calrl.hubbly.commands.subcommands.worlds; +package me.calrl.hubbly.commands.worlds; import me.calrl.hubbly.Hubbly; import me.calrl.hubbly.enums.Permissions; -import me.calrl.hubbly.interfaces.SubCommand; +import me.calrl.hubbly.enums.Result; import me.calrl.hubbly.utils.CommandNode; import me.calrl.hubbly.utils.MessageBuilder; import org.bukkit.Bukkit; import org.bukkit.World; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import java.util.Collections; import java.util.List; -public class CheckCommand extends CommandNode { +public class CheckWorldCommand extends CommandNode { private final Hubbly plugin; - public CheckCommand(Hubbly plugin) { - super("add"); + public CheckWorldCommand(Hubbly plugin) { + super("check"); this.plugin = plugin; } @Override - public void execute(CommandSender sender, String[] args, int depth) { + public Result execute(CommandSender sender, String[] args, int depth) { if(!sender.hasPermission(Permissions.COMMAND_WORLDS_CHECK.getPermission())) { new MessageBuilder(plugin).setKey("no_permission_command").setPlayer(sender).send(); - return; + return Result.NO_PERMISSION; } if(args.length <= depth) { new MessageBuilder(plugin).setKey("subcommands.worlds.check.usage").setPlayer(sender).send(); - return; + return Result.USAGE_PRINTED; } String worldName = args[depth]; @@ -41,7 +39,7 @@ public void execute(CommandSender sender, String[] args, int depth) { .setPlayer(sender) .replace("%world%", worldName) .send(); - return; + return Result.FAILURE; } MessageBuilder builder = new MessageBuilder(plugin); @@ -51,13 +49,14 @@ public void execute(CommandSender sender, String[] args, int depth) { builder.setKey("subcommands.worlds.check.disabled") .setPlayer(sender) .replace("%world%", world.getName()).send(); - return; + return Result.SUCCESS; } builder.setKey("subcommands.worlds.check.enabled") .setPlayer(sender) .replace("%world%", world.getName()).send(); + return Result.SUCCESS; } @Override diff --git a/src/main/java/me/calrl/hubbly/commands/worlds/ListWorldCommand.java b/src/main/java/me/calrl/hubbly/commands/worlds/ListWorldCommand.java new file mode 100644 index 0000000..03421ca --- /dev/null +++ b/src/main/java/me/calrl/hubbly/commands/worlds/ListWorldCommand.java @@ -0,0 +1,33 @@ +package me.calrl.hubbly.commands.worlds; + +import me.calrl.hubbly.Hubbly; +import me.calrl.hubbly.enums.Result; +import me.calrl.hubbly.utils.CommandNode; +import me.calrl.hubbly.utils.MessageBuilder; +import org.bukkit.World; +import org.bukkit.command.CommandSender; + +import java.util.List; +import java.util.stream.Collectors; + +public class ListWorldCommand extends CommandNode { + private Hubbly plugin; + public ListWorldCommand(Hubbly plugin) { + super("list"); + this.plugin = plugin; + } + + @Override + public Result execute(CommandSender sender, String[] args, int depth) { + + List disabledWorlds = plugin.getDisabledWorldsManager().getDisabledWorlds(); + String disabledWorldNames = disabledWorlds + .stream() + .map(World::getName) + .collect(Collectors.joining(", ")); + + new MessageBuilder(plugin).usePrefix(true).setPlayer(sender).setMessage(disabledWorldNames).send(); + + return Result.SUCCESS; + } +} diff --git a/src/main/java/me/calrl/hubbly/commands/subcommands/worlds/RemoveCommand.java b/src/main/java/me/calrl/hubbly/commands/worlds/RemoveWorldCommand.java similarity index 80% rename from src/main/java/me/calrl/hubbly/commands/subcommands/worlds/RemoveCommand.java rename to src/main/java/me/calrl/hubbly/commands/worlds/RemoveWorldCommand.java index 38b5c9f..15650b7 100644 --- a/src/main/java/me/calrl/hubbly/commands/subcommands/worlds/RemoveCommand.java +++ b/src/main/java/me/calrl/hubbly/commands/worlds/RemoveWorldCommand.java @@ -1,36 +1,34 @@ -package me.calrl.hubbly.commands.subcommands.worlds; +package me.calrl.hubbly.commands.worlds; import me.calrl.hubbly.Hubbly; import me.calrl.hubbly.enums.Permissions; -import me.calrl.hubbly.interfaces.SubCommand; +import me.calrl.hubbly.enums.Result; import me.calrl.hubbly.utils.CommandNode; import me.calrl.hubbly.utils.MessageBuilder; import org.bukkit.Bukkit; import org.bukkit.World; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import java.util.Collections; import java.util.List; -public class RemoveCommand extends CommandNode { +public class RemoveWorldCommand extends CommandNode { private Hubbly plugin; - public RemoveCommand(Hubbly plugin) { - super("add"); + public RemoveWorldCommand(Hubbly plugin) { + super("remove"); this.plugin = plugin; } @Override - public void execute(CommandSender sender, String[] args, int depth) { + public Result execute(CommandSender sender, String[] args, int depth) { if(!sender.hasPermission(Permissions.COMMAND_WORLDS_REMOVE.getPermission())) { new MessageBuilder(plugin).setKey("no_permission_command").setPlayer(sender).send(); - return; + return Result.NO_PERMISSION; } if(args.length <= depth) { new MessageBuilder(plugin).setKey("subcommands.worlds.remove.usage").setPlayer(sender).send(); - return; + return Result.USAGE_PRINTED; } String worldName = args[depth]; @@ -41,7 +39,7 @@ public void execute(CommandSender sender, String[] args, int depth) { .setPlayer(sender) .replace("%world%", worldName) .send(); - return; + return Result.FAILURE; } plugin.getDisabledWorldsManager().removeWorld(world); @@ -51,6 +49,7 @@ public void execute(CommandSender sender, String[] args, int depth) { .setPlayer(sender) .replace("%world%", world.getName()) .send(); + return Result.SUCCESS; } @Override diff --git a/src/main/java/me/calrl/hubbly/commands/worlds/WorldsCommand.java b/src/main/java/me/calrl/hubbly/commands/worlds/WorldsCommand.java new file mode 100644 index 0000000..c5626f4 --- /dev/null +++ b/src/main/java/me/calrl/hubbly/commands/worlds/WorldsCommand.java @@ -0,0 +1,59 @@ +package me.calrl.hubbly.commands.worlds; + +import me.calrl.hubbly.Hubbly; +import me.calrl.hubbly.enums.Permissions; +import me.calrl.hubbly.enums.Result; +import me.calrl.hubbly.utils.CommandNode; +import me.calrl.hubbly.utils.MessageBuilder; +import org.bukkit.command.CommandSender; + +import java.util.List; +import java.util.Map; + +public class WorldsCommand extends CommandNode { + + private Hubbly plugin; + public WorldsCommand(Hubbly plugin) { + super("worlds"); + this.plugin = plugin; + + this.loadNodes(); + } + + private void loadNodes() { + addChild("add", new AddWorldCommand(plugin)); + addChild("remove", new RemoveWorldCommand(plugin)); + addChild("check", new CheckWorldCommand(plugin)); + addChild("list", new ListWorldCommand(plugin)); + } + + @Override + public Result execute(CommandSender sender, String[] args, int depth) { + if(!sender.hasPermission(Permissions.COMMAND_WORLDS.getPermission())) { + new MessageBuilder(plugin).setKey("no_permission_command").setPlayer(sender).send(); + return Result.NO_PERMISSION; + } + + Result result = this.executeIfChildPresent(sender, args, depth); + if(result != Result.NO_CHILD) { + return result; + } + + Map children = this.getChildren(); + String subCommands = String.join(" | ", children.keySet()); + + new MessageBuilder(plugin) + .setKey("subcommands.worlds.usage") + .replace("%args%", subCommands) + .setPlayer(sender) + .send(); + + return Result.USAGE_PRINTED; + } + + @Override + public List tabComplete(CommandSender sender, String[] args, int depth) { + return super.tabComplete(sender, args, depth); + } + +} diff --git a/src/main/java/me/calrl/hubbly/enums/Permissions.java b/src/main/java/me/calrl/hubbly/enums/Permissions.java index 9b09bd2..482eba0 100644 --- a/src/main/java/me/calrl/hubbly/enums/Permissions.java +++ b/src/main/java/me/calrl/hubbly/enums/Permissions.java @@ -32,6 +32,7 @@ public enum Permissions { COMMAND_HELP("command.help"), COMMAND_CONVERT("command.convert"), COMMAND_MENU("command.menu"), + COMMAND_DEBUG("command.debug"), COMMAND_WORLDS("commands.worlds"), COMMAND_WORLDS_ADD("commands.worlds.add"), diff --git a/src/main/java/me/calrl/hubbly/enums/Result.java b/src/main/java/me/calrl/hubbly/enums/Result.java new file mode 100644 index 0000000..9edc3cd --- /dev/null +++ b/src/main/java/me/calrl/hubbly/enums/Result.java @@ -0,0 +1,15 @@ +package me.calrl.hubbly.enums; + +public enum Result { + SUCCESS, + FAILURE, + INVALID_ARGS, + NO_PERMISSION, + USAGE_PRINTED, + PLAYER_ONLY, + CONSOLE_ONLY, + COOLDOWN, + ALREADY_EXISTS, + NOTHING_TO_DO, + NO_CHILD +} diff --git a/src/main/java/me/calrl/hubbly/functions/BossBarManager.java b/src/main/java/me/calrl/hubbly/functions/BossBarManager.java index 7d9660c..e9cd2de 100644 --- a/src/main/java/me/calrl/hubbly/functions/BossBarManager.java +++ b/src/main/java/me/calrl/hubbly/functions/BossBarManager.java @@ -115,11 +115,12 @@ public void removeAllBossBars() { public void reAddAllBossBars() { DisabledWorlds disabledWorlds = plugin.getDisabledWorldsManager(); - boolean isEnabled = config.getBoolean("player.bossbar.enabled"); + FileConfiguration config = plugin.getConfig(); + boolean isEnaled = config.getBoolean("player.bossbar.enabled"); for (Player player : Bukkit.getOnlinePlayers()) { - if(disabledWorlds.inDisabledWorld(player.getWorld())) continue; - if(!isEnabled) return; - this.createBossBar(player); + if(disabledWorlds.inDisabledWorld(player.getWorld())) return; + if(!isEnaled) return; + createBossBar(player); } } diff --git a/src/main/java/me/calrl/hubbly/interfaces/ISpawnTeleportTask.java b/src/main/java/me/calrl/hubbly/interfaces/ISpawnTeleportTask.java new file mode 100644 index 0000000..ce8af34 --- /dev/null +++ b/src/main/java/me/calrl/hubbly/interfaces/ISpawnTeleportTask.java @@ -0,0 +1,16 @@ +package me.calrl.hubbly.interfaces; + +import me.calrl.hubbly.enums.Result; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +public interface ISpawnTeleportTask { + + Result start(); + Result cancel(); + void setTimer(long value); + Location getStartLocation(); + BukkitRunnable getTask(); + Player getPlayer(); +} diff --git a/src/main/java/me/calrl/hubbly/listeners/items/movement/RodListener.java b/src/main/java/me/calrl/hubbly/listeners/items/movement/RodListener.java index 283ea17..5e994a3 100644 --- a/src/main/java/me/calrl/hubbly/listeners/items/movement/RodListener.java +++ b/src/main/java/me/calrl/hubbly/listeners/items/movement/RodListener.java @@ -32,7 +32,6 @@ private void onFishingRodUse(PlayerFishEvent event) { if(!player.hasPermission(Permissions.USE_GRAPPLING_HOOK.getPermission())) return; ItemMeta meta = player.getInventory().getItemInMainHand().getItemMeta(); - if (event.getState() != PlayerFishEvent.State.FAILED_ATTEMPT && event.getState() != PlayerFishEvent.State.IN_GROUND && event.getState() != PlayerFishEvent.State.REEL_IN) return; diff --git a/src/main/java/me/calrl/hubbly/listeners/player/PlayerMoveListener.java b/src/main/java/me/calrl/hubbly/listeners/player/PlayerMoveListener.java new file mode 100644 index 0000000..94d1f77 --- /dev/null +++ b/src/main/java/me/calrl/hubbly/listeners/player/PlayerMoveListener.java @@ -0,0 +1,42 @@ +package me.calrl.hubbly.listeners.player; + +import me.calrl.hubbly.Hubbly; +import me.calrl.hubbly.managers.DebugMode; +import me.calrl.hubbly.managers.SpawnTaskManager; +import me.calrl.hubbly.tasks.spawn.SpawnTeleportTask; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; + +import java.util.UUID; + +public class PlayerMoveListener implements Listener { + private SpawnTaskManager registry; + + public PlayerMoveListener(Hubbly plugin) { + this.registry = plugin.getManagerFactory().getSpawnTaskManager(); + } + @EventHandler + private void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + if (!registry.isTracked(uuid)) { + return; + } + SpawnTeleportTask task = (SpawnTeleportTask) registry.getTask(uuid); + Location from = task.getStartLocation(); + Location to = event.getTo(); + if(to == null) { + return; + } + if (from.getX() == to.getX() && from.getZ() == to.getZ() && from.getY() == to.getY()) { + return; + } + new DebugMode().info("MOVED"); + task.cancel(); + registry.unregister(uuid); + + } +} diff --git a/src/main/java/me/calrl/hubbly/listeners/world/WorldEventListeners.java b/src/main/java/me/calrl/hubbly/listeners/world/WorldEventListeners.java index 60dae56..a257b24 100644 --- a/src/main/java/me/calrl/hubbly/listeners/world/WorldEventListeners.java +++ b/src/main/java/me/calrl/hubbly/listeners/world/WorldEventListeners.java @@ -55,6 +55,7 @@ public WorldEventListeners(Hubbly plugin) { this.plugin = plugin; this.config = plugin.getConfig(); this.bossBarManager = plugin.getBossBarManager(); + this.plugin.getLogger().info("Loaded WorldEventListeners"); } /** @@ -84,7 +85,7 @@ private boolean inDisabledWorld(World world) { private void onBlockPlace(BlockPlaceEvent event) { Player player = event.getPlayer(); if(inDisabledWorld(player)) return; - if(player.hasPermission("hubbly.bypass.place") || player.isOp()) return; + if(player.hasPermission("hubbly.bypass.place") ) return; if(config.getBoolean("cancel_events.block_place")) { event.setCancelled(true); } @@ -94,7 +95,7 @@ private void onBlockPlace(BlockPlaceEvent event) { private void onBlockBreak(BlockBreakEvent event) { Player player = event.getPlayer(); if(inDisabledWorld(player)) return; - if(player.hasPermission("hubbly.bypass.break") || player.isOp()) return; + if(player.hasPermission("hubbly.bypass.break") ) return; if (config.getBoolean("cancel_events.block_break")) { event.setCancelled(true); @@ -138,7 +139,7 @@ private void onWorldLoad(WorldLoadEvent event) { private void onItemDrop(PlayerDropItemEvent event) { Player player = event.getPlayer(); if(inDisabledWorld(player)) return; - if (player.hasPermission("hubbly.bypass.item.drop") || player.isOp()) return; + if (player.hasPermission("hubbly.bypass.item.drop") ) return; if(config.getBoolean("cancel_events.item_drop")) { event.setCancelled(true); } @@ -147,7 +148,7 @@ private void onItemDrop(PlayerDropItemEvent event) { private void onItemPickup(EntityPickupItemEvent event) { if (event.getEntity() instanceof Player player) { if (inDisabledWorld(player)) return; - if (player.hasPermission("hubbly.bypass.item.pickup") || player.isOp()) return; + if (player.hasPermission("hubbly.bypass.item.pickup") ) return; if (config.getBoolean("cancel_events.item_pickup")) { event.setCancelled(true); } @@ -207,7 +208,7 @@ private void onAnimalEat(EntityChangeBlockEvent event) { private void onItemThrow(PlayerDropItemEvent event) { Player player = event.getPlayer(); if(config.getBoolean("cancel_events.item_throw", true)) { - if (player.hasPermission("hubbly.bypass.item.throw") || player.isOp()) return; + if (player.hasPermission("hubbly.bypass.item.throw") ) return; if (inDisabledWorld(player)) return; } else { diff --git a/src/main/java/me/calrl/hubbly/managers/AnnouncementsManager.java b/src/main/java/me/calrl/hubbly/managers/AnnouncementsManager.java index 858dca0..c9b535e 100644 --- a/src/main/java/me/calrl/hubbly/managers/AnnouncementsManager.java +++ b/src/main/java/me/calrl/hubbly/managers/AnnouncementsManager.java @@ -69,7 +69,6 @@ private void loadAnnouncements() { List messages = section.getStringList(key); String[] messageArray = messages.toArray(new String[0]); announcements.add(messageArray); - debugMode.info(announcements.toString()); state.set(true); } } catch (Exception e) { diff --git a/src/main/java/me/calrl/hubbly/managers/DisabledWorlds.java b/src/main/java/me/calrl/hubbly/managers/DisabledWorlds.java index 5371f21..1405d14 100644 --- a/src/main/java/me/calrl/hubbly/managers/DisabledWorlds.java +++ b/src/main/java/me/calrl/hubbly/managers/DisabledWorlds.java @@ -18,6 +18,7 @@ package me.calrl.hubbly.managers; import me.calrl.hubbly.Hubbly; +import me.calrl.hubbly.enums.Result; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -44,8 +45,9 @@ public boolean inDisabledWorld(Location location) { } public void setDisabledWorlds() { - List disabledWorldsList = this.getConfigWorldList(); DebugMode debugMode = new DebugMode(); + List disabledWorldsList = this.getConfigWorldList(); + debugMode.info("Worlds to disable: " + disabledWorldsList); if(disabledWorldsList.isEmpty()) { debugMode.info("No worlds to register"); } @@ -76,37 +78,51 @@ private List getConfigWorldList() { } List disabledWorldsList = config.getStringList("disabled-worlds"); + new DebugMode().info("DWList: " + disabledWorldsList); boolean isInverted = config.getBoolean("invert", false); if (isInverted) { - disabledWorldsList = this.getInvertedWorlds(); + disabledWorldsList = this.getInvertedWorlds(disabledWorldsList); } return disabledWorldsList; } - private List getInvertedWorlds() { + private List getInvertedWorlds(List current) { List allWorlds = Bukkit.getWorlds(); List invertedWorlds = new ArrayList<>(); for (World world : allWorlds) { - if (!disabledWorlds.contains(world)) { + if (!current.contains(world.getName())) { invertedWorlds.add(world.getName()); } } return invertedWorlds; } + public void clear() { + this.disabledWorlds.clear(); + } + public void addWorld(World world) { boolean isValid = this.checkValidity(world); - if(!isValid) return; + if (!isValid) return; DebugMode debugMode = new DebugMode(); - if(disabledWorlds.contains(world)) { + if (disabledWorlds.contains(world)) { debugMode.info("World is already in DisabledWorlds list: "); } disabledWorlds.add(world); + this.updateConfig(); + } + + public Result updateConfig() { + List worldNames = this.getDisabledWorldNames(); + plugin.getConfig().set("disabled-worlds", worldNames); + plugin.saveConfig(); + + return Result.SUCCESS; } public boolean checkWorld(World world) { @@ -138,12 +154,21 @@ public void removeWorld(World world) { } disabledWorlds.remove(world); + this.updateConfig(); } public List getDisabledWorlds() { return this.disabledWorlds; } + public List getDisabledWorldNames() { + List list = new ArrayList<>(); + for (World disabledWorld : this.disabledWorlds) { + list.add(disabledWorld.getName()); + } + return list; + } + public void reload() { disabledWorlds.clear(); this.setDisabledWorlds(); diff --git a/src/main/java/me/calrl/hubbly/managers/LockChat.java b/src/main/java/me/calrl/hubbly/managers/LockChat.java index b2051f3..8d2324c 100644 --- a/src/main/java/me/calrl/hubbly/managers/LockChat.java +++ b/src/main/java/me/calrl/hubbly/managers/LockChat.java @@ -24,7 +24,9 @@ public class LockChat { private boolean isChatLocked; public LockChat(Hubbly plugin) { this.plugin = plugin; - isChatLocked = false; + isChatLocked = plugin.getConfig().getBoolean("lock_chat"); + String msg = isChatLocked ? "Chat is LOCKED" : "Chat is UNLOCKED"; + new DebugMode().info(msg); } public void flipChatLock() { isChatLocked = !isChatLocked; diff --git a/src/main/java/me/calrl/hubbly/managers/ManagerFactory.java b/src/main/java/me/calrl/hubbly/managers/ManagerFactory.java index d41f138..dc14f19 100644 --- a/src/main/java/me/calrl/hubbly/managers/ManagerFactory.java +++ b/src/main/java/me/calrl/hubbly/managers/ManagerFactory.java @@ -6,6 +6,7 @@ public class ManagerFactory { private Hubbly plugin; private TridentDataManager tridentDataManager; + private SpawnTaskManager spawnTaskManager; public ManagerFactory(Hubbly plugin) { this.start(); @@ -13,9 +14,15 @@ public ManagerFactory(Hubbly plugin) { public void start() { this.tridentDataManager = new TridentDataManager(); + this.spawnTaskManager = new SpawnTaskManager(); } public TridentDataManager getTridentDataManager() { return this.tridentDataManager; } + + public SpawnTaskManager getSpawnTaskManager() { + return this.spawnTaskManager; + } + } diff --git a/src/main/java/me/calrl/hubbly/managers/SpawnTaskManager.java b/src/main/java/me/calrl/hubbly/managers/SpawnTaskManager.java new file mode 100644 index 0000000..e463a7e --- /dev/null +++ b/src/main/java/me/calrl/hubbly/managers/SpawnTaskManager.java @@ -0,0 +1,63 @@ +package me.calrl.hubbly.managers; + +import me.calrl.hubbly.enums.Result; +import me.calrl.hubbly.tasks.ITask; +import me.calrl.hubbly.tasks.spawn.SpawnTeleportTask; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class SpawnTaskManager { + private final Map locationMap = new HashMap<>(); + private final Map tasks = new HashMap<>(); + + public Result register(Player player, Location location, SpawnTeleportTask task) { + UUID uuid = player.getUniqueId(); + register(uuid, location, task); + return Result.SUCCESS; + } + + public Result register(UUID uuid, Location location, SpawnTeleportTask task) { + locationMap.put(uuid, location); + tasks.put(uuid, task); + return Result.SUCCESS; + } + + public Result unregister(UUID uuid) { + locationMap.remove(uuid); + tasks.remove(uuid); + return Result.SUCCESS; + } + + public ITask getTask(Player player) { + UUID uuid = player.getUniqueId(); + return this.getTask(uuid); + } + + public ITask getTask(UUID uuid) { + return tasks.get(uuid); + } + + public Location getStartLocation(Player player) { + UUID uuid = player.getUniqueId(); + return this.getStartLocation(uuid); + } + + public Location getStartLocation(UUID uuid) { + return this.locationMap.get(uuid); + } + + public boolean hasMoved(UUID uuid, Location newLocation) { + Location location = this.getStartLocation(uuid); + return !location.equals(newLocation); + } + + public boolean isTracked(UUID uuid) { + return this.locationMap.containsKey(uuid); + } + + +} diff --git a/src/main/java/me/calrl/hubbly/managers/SubCommandManager.java b/src/main/java/me/calrl/hubbly/managers/SubCommandManager.java index 93d1d6d..49da7bb 100644 --- a/src/main/java/me/calrl/hubbly/managers/SubCommandManager.java +++ b/src/main/java/me/calrl/hubbly/managers/SubCommandManager.java @@ -1,16 +1,14 @@ package me.calrl.hubbly.managers; import me.calrl.hubbly.Hubbly; +import me.calrl.hubbly.commands.debug.DebugCommand; import me.calrl.hubbly.commands.subcommands.*; -import me.calrl.hubbly.commands.subcommands.worlds.WorldsCommand; +import me.calrl.hubbly.commands.worlds.WorldsCommand; import me.calrl.hubbly.interfaces.SubCommand; import me.calrl.hubbly.utils.CommandNode; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; public class SubCommandManager { private final Map subCommands; @@ -58,6 +56,7 @@ public Map getSubCommands() { public void loadNodes() { this.registerNode(new WorldsCommand(plugin)); + this.registerNode(new DebugCommand(plugin)); new DebugMode().info("Loaded all WorldsCommand nodes"); } public void registerNode(CommandNode node) { diff --git a/src/main/java/me/calrl/hubbly/tasks/ITask.java b/src/main/java/me/calrl/hubbly/tasks/ITask.java new file mode 100644 index 0000000..681b404 --- /dev/null +++ b/src/main/java/me/calrl/hubbly/tasks/ITask.java @@ -0,0 +1,14 @@ +package me.calrl.hubbly.tasks; + +import me.calrl.hubbly.enums.Result; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +public interface ITask { + Result start(); + Result cancel(); + void setTimer(long value); + long getTimer(); + BukkitRunnable getTask(); + Player getPlayer(); +} diff --git a/src/main/java/me/calrl/hubbly/tasks/spawn/SpawnTeleportTask.java b/src/main/java/me/calrl/hubbly/tasks/spawn/SpawnTeleportTask.java new file mode 100644 index 0000000..6223325 --- /dev/null +++ b/src/main/java/me/calrl/hubbly/tasks/spawn/SpawnTeleportTask.java @@ -0,0 +1,92 @@ +package me.calrl.hubbly.tasks.spawn; + +import me.calrl.hubbly.Hubbly; +import me.calrl.hubbly.enums.Result; +import me.calrl.hubbly.managers.DebugMode; +import me.calrl.hubbly.managers.SpawnTaskManager; +import me.calrl.hubbly.tasks.ITask; +import me.calrl.hubbly.utils.MessageBuilder; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +public class SpawnTeleportTask implements ITask { + + private final Player player; + private final Location startLocation; + private final Hubbly plugin; + private final BukkitRunnable task; + private final Location spawn; + private final SpawnTaskManager registry; + private long timer; + public SpawnTeleportTask(Hubbly plugin, Player player, long timer) { + this.plugin = plugin; + this.player = player; + this.startLocation = player.getLocation(); + this.spawn = plugin.getUtils().getSpawn(); + this.registry = plugin.getManagerFactory().getSpawnTaskManager(); + this.task = new BukkitRunnable() { + @Override + public void run() { + if(player.isOnline()) { + player.teleport(spawn); + cleanup(); + } + } + }; + this.timer = timer; + + } + public Result start() { + registry.register(this.player.getUniqueId(), this.startLocation, this); + this.task.runTaskLater(this.plugin, 20L * this.timer); + + new MessageBuilder(this.plugin) + .setPlayer(this.player) + .setKey("teleporting") + .replace("%value%", String.valueOf(this.timer)) + .send(); + + return Result.SUCCESS; + } + + public Result cancel() { + this.task.cancel(); + + this.cleanup(); + + //todo: messagebuilder sends message + new MessageBuilder(this.plugin) + .setKey("teleport_cancelled") + .setPlayer(player) + .send(); + return Result.SUCCESS; + } + + public Result cleanup() { + this.registry.unregister(this.player.getUniqueId()); + new DebugMode().info("Cleaned up SpawnTeleportTask successfully!"); + return Result.SUCCESS; + } + + public void setTimer(long value) { + this.timer = value; + } + + @Override + public long getTimer() { + return this.timer; + } + + public Location getStartLocation() { + return startLocation; + } + + public BukkitRunnable getTask() { + return this.task; + } + + public Player getPlayer() { + return this.player; + } +} diff --git a/src/main/java/me/calrl/hubbly/utils/CommandNode.java b/src/main/java/me/calrl/hubbly/utils/CommandNode.java index 96ca4f5..62b4d79 100644 --- a/src/main/java/me/calrl/hubbly/utils/CommandNode.java +++ b/src/main/java/me/calrl/hubbly/utils/CommandNode.java @@ -1,5 +1,6 @@ package me.calrl.hubbly.utils; +import me.calrl.hubbly.enums.Result; import org.bukkit.command.CommandSender; import java.util.*; @@ -19,7 +20,16 @@ public void addChild(String identifier, CommandNode child) { public boolean matches(String input) { return this.identifier.equalsIgnoreCase(input); } - public abstract void execute(CommandSender sender, String[] args, int depth); + public abstract Result execute(CommandSender sender, String[] args, int depth); + public Result executeIfChildPresent(CommandSender sender, String[] args, int depth) { + if(args.length > depth) { + CommandNode node = this.children.get(args[depth].toLowerCase()); + if(node != null) { + return node.execute(sender, args, depth + 1); + } + } + return Result.NO_CHILD; + } public List tabComplete(CommandSender sender, String[] args, int depth) { if (args.length == depth + 1) { diff --git a/src/main/java/me/calrl/hubbly/utils/ItemBuilder.java b/src/main/java/me/calrl/hubbly/utils/ItemBuilder.java index 3c0a986..2e48666 100644 --- a/src/main/java/me/calrl/hubbly/utils/ItemBuilder.java +++ b/src/main/java/me/calrl/hubbly/utils/ItemBuilder.java @@ -18,6 +18,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.SkullMeta; diff --git a/src/main/java/me/calrl/hubbly/utils/MessageBuilder.java b/src/main/java/me/calrl/hubbly/utils/MessageBuilder.java index babbed9..c82029a 100644 --- a/src/main/java/me/calrl/hubbly/utils/MessageBuilder.java +++ b/src/main/java/me/calrl/hubbly/utils/MessageBuilder.java @@ -12,7 +12,7 @@ public class MessageBuilder { private Player player; private Hubbly plugin; - private LocaleKey key; + private String key; private String content; private LocaleManager localeManager = null; private boolean usePrefix = true; @@ -23,15 +23,25 @@ public MessageBuilder() { public MessageBuilder(Hubbly plugin) { this.plugin = plugin; + this.localeManager = plugin.getLocaleManager(); } public MessageBuilder(Hubbly plugin, Player player) { this.player = player; this.plugin = plugin; + this.localeManager = plugin.getLocaleManager(); } + public MessageBuilder(Hubbly plugin, Player player, String key) { + this.plugin = plugin; + this.player = player; + this.key = key; + + this.localeManager = this.plugin.getLocaleManager(); + } + public MessageBuilder setKey(String key) { String msg; if(player != null) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6ddc16c..608a118 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -82,6 +82,7 @@ spawn: #YAW AND PITCH WILL ROUND TO {-135, -90, -45, 0, 45, 90, 135} WHEN YOU USE /SETSPAWN, YOU CAN MANUALLY OVERRIDE THIS HERE yaw: 0 pitch: 0 + timer: 2 #-----------------# diff --git a/src/main/resources/languages/en.yml b/src/main/resources/languages/en.yml index b4e5414..8b9dde9 100644 --- a/src/main/resources/languages/en.yml +++ b/src/main/resources/languages/en.yml @@ -17,10 +17,12 @@ invalid_argument: Invalid argument %value% invalid_world: World %world% does not exist unknown_player: Player %player% not found arg_must_be_number: Argument %value% must be a number +teleporting: Don't move! Teleporting in %value% seconds +teleport_cancelled: You moved, teleport cancelled. -# No PAPI support, only %player% placeholder to get the person who locked the chat. -chat_locked: Chat has been locked by %player% -chat_unlocked: Chat has been unlocked by %player% +# No PAPI support, only %player_name% placeholder to get the person who locked the chat. +chat_locked: Chat has been locked by %player_name% +chat_unlocked: Chat has been unlocked by %player_name% update: new_update: @@ -82,8 +84,10 @@ subcommands: menu: usage: /hubbly menu description: Opens a provided menu + debug: + usage: /hubbly debug worlds: - usage: /hubbly worlds + usage: /hubbly worlds <%args%> description: add: usage: /hubbly worlds add diff --git a/src/main/resources/languages/pt.yml b/src/main/resources/languages/pt.yml new file mode 100644 index 0000000..45d0772 --- /dev/null +++ b/src/main/resources/languages/pt.yml @@ -0,0 +1,104 @@ +no_console: "Só jogadores podem usar este comando!" +no_permission_command: Não tens permissão para usar este comando! +no_permission_use: Não tens permissão para usar isto! +reload: Hubbly plugin recarregado +fly: + enable: Modo de voo ativado. + disable: Modo de voo desativado. +no_fly_enabled: Flight está desativado na config +blocked_command: Comando desconhecido. Use "/help" para ajuda +blocked_message: Por favor não use essa palavra! +success: Sucesso! +failure: Falha! +unknown_command: Comando desconhecido. Use '/hubbly help' para a lista de comandos. +unknown_item: Item %value% não encontrado +invalid_amount: Quantidade inválida %value% +invalid_argument: Argumento inválido %value% +invalid_world: Mundo %world% não existe +unknown_player: Jogador %player% não encontrado +arg_must_be_number: Argumento %value% tem de ser um número +teleporting: Não mexa! Teletransportando em %value% segundos +teleport_cancelled: Mexeu, teletransporte cancelado. + +# No PAPI support, only %player_name% placeholder to get the person who locked the chat. +chat_locked: Chat foi bloqueado por %player_name% +chat_unlocked: Chat foi desbloqueado por %player_name% + +update: + new_update: + Uma atualização está disponível! Hubbly %new% pode ser transferido em SpigotMC, + Você está atualmente em %current% + no_update: Hubbly %current% está atualizado + error: Não foi possível verificar se há uma nova versão... + +action: + errors: + null: Dados da ação estão nulos..." + +anti_wdl_notify: Jogador %player% tentou descarregar o mundo +usage: + hubbly: "Uso: /hubbly " + +commands: + hubbly: + usage: /hubbly + description: Comando principal do plugin. + setspawn: + usage: /setspawn + description: Define o local de spawn para sua posição atual. + spawn: + usage: /spawn + description: Teletransporta você para o local de spawn. + fly: + usage: /fly + description: Alterna o modo de vôo para o jogador. + clearchat: + usage: /clearchat + description: Limpa o chat para todos os jogadores. + lockchat: + usage: /lockchat + description: Bloqueia ou desbloqueia o chat para todos os jogadores. + +subcommands: + version: + usage: /hubbly version + description: Mostra a versão atual do plugin. + help: + usage: /hubbly help + description: Mosta a lista de comandos disponíveis. + reload: + usage: /hubbly reload + description: Recarrega a configuração do plugin. + nextannouncement: + usage: /hubbly nextannouncement + description: Envia o próximo anúncio agendado. + give: + usage: /hubbly give [amount] [slot] + description: Dá um item a um jogador com valor e slot opcionais. + messages: + give_item: "Deu %amount% %item% para %player%" + give_item_with_slot: "Deu %amount% %item% para %player% no slot %slot%" + convert: + usage: /hubbly convert + description: Converte arquivos + menu: + usage: /hubbly menu + description: Abre um menu fornecido + debug: + usage: /hubbly debug + worlds: + usage: /hubbly worlds <%args%> + description: + add: + usage: /hubbly worlds add + description: + message: Adicionado %world% para a lista de mundos desativados + remove: + usage: /hubbly worlds remove + description: + message: Removido %world% da lista de mundos desativados + check: + usage: /hubbly worlds check + description: + enabled: "Hubbly está abilitado em mundo: %world%" + disabled: "Hubbly está desabilitado em mundo: %world%" \ No newline at end of file diff --git a/src/test/java/me/calrl/hubbly/PluginTestBase.java b/src/test/java/me/calrl/hubbly/PluginTestBase.java index f507558..f76d3c9 100644 --- a/src/test/java/me/calrl/hubbly/PluginTestBase.java +++ b/src/test/java/me/calrl/hubbly/PluginTestBase.java @@ -3,37 +3,77 @@ import be.seeseemelk.mockbukkit.MockBukkit; import be.seeseemelk.mockbukkit.ServerMock; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; + import static org.junit.jupiter.api.Assertions.assertNotNull; public abstract class PluginTestBase { protected static ServerMock server; - protected static Hubbly plugin; + public static Hubbly plugin; + + @BeforeAll + public static void startup() throws Exception { + + if (!MockBukkit.isMocked()) { + server = MockBukkit.mock(); + } else { + server = MockBukkit.getMock(); + } + + plugin = (Hubbly) MockBukkit.load(Hubbly.class); + plugin.onEnable(); + + long start = System.currentTimeMillis(); + while (!plugin.isLoaded()) { + try { + if (System.currentTimeMillis() - start > 5000) { + throw new RuntimeException("Hubbly did not finish loading in time"); + } + Thread.sleep(10); + } catch (Exception e) { + throw new Exception(e.getMessage()); + } + } + + loadFile("config.yml"); + loadFile("items.yml"); + loadFile("menus/selector.yml"); + loadFile("menus/socials.yml"); + } @BeforeEach public void init() { - System.out.println("Starting init"); - server = MockBukkit.mock(); - - server.addSimpleWorld("world_nether"); - server.addSimpleWorld("world"); Hubbly.enableTestMode(); - plugin = MockBukkit.load(Hubbly.class); - assertNotNull(plugin, "Plugin failed to load"); - System.out.println("Ending init"); - } - @AfterEach - public void cleanup() { - MockBukkit.unmock(); + assertNotNull(plugin, "Plugin failed to load"); } +// @AfterEach +// public void cleanup() { +// MockBukkit.unmock(); +// } +// @AfterAll public static void clean() { MockBukkit.unmock(); + System.out.println("cleanup!"); + } + + private static void loadFile(String resourcePath) throws IOException { + Path target = plugin.getDataFolder().toPath().resolve(resourcePath); + Files.createDirectories(target.getParent()); + + try (InputStream in = PluginTestBase.class.getClassLoader().getResourceAsStream(resourcePath)) { + assertNotNull(in, "Missing test resource: " + resourcePath); + Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING); + } } } diff --git a/src/test/java/me/calrl/hubbly/commands/FlyCommandTest.java b/src/test/java/me/calrl/hubbly/commands/FlyCommandTest.java index b729518..df13549 100644 --- a/src/test/java/me/calrl/hubbly/commands/FlyCommandTest.java +++ b/src/test/java/me/calrl/hubbly/commands/FlyCommandTest.java @@ -1,7 +1,9 @@ package me.calrl.hubbly.commands; import be.seeseemelk.mockbukkit.entity.PlayerMock; +import me.calrl.hubbly.Hubbly; import me.calrl.hubbly.PluginTestBase; +import me.calrl.hubbly.managers.LocaleManager; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.persistence.PersistentDataType; @@ -62,4 +64,15 @@ public void testFlyTogglesCorrectly() { byte newState = player.getPersistentDataContainer().get(plugin.FLY_KEY, PersistentDataType.BYTE); assertEquals((byte) 0, newState); } + + @Test + public void testHubbly() { + Hubbly plugin = Hubbly.getInstance(); + + LocaleManager manager = plugin.getLocaleManager(); + + String lang = manager.getDefaultLanguage(); + + assertEquals("en", lang); + } } diff --git a/src/test/java/me/calrl/hubbly/listeners/player/PlayerMoveListenerTests.java b/src/test/java/me/calrl/hubbly/listeners/player/PlayerMoveListenerTests.java new file mode 100644 index 0000000..e96838d --- /dev/null +++ b/src/test/java/me/calrl/hubbly/listeners/player/PlayerMoveListenerTests.java @@ -0,0 +1,62 @@ +package me.calrl.hubbly.listeners.player; + +import be.seeseemelk.mockbukkit.entity.PlayerMock; +import me.calrl.hubbly.PluginTestBase; +import me.calrl.hubbly.enums.Result; +import me.calrl.hubbly.managers.SpawnTaskManager; +import me.calrl.hubbly.tasks.spawn.SpawnTeleportTask; +import org.bukkit.Location; +import org.bukkit.event.player.PlayerMoveEvent; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class PlayerMoveListenerTests extends PluginTestBase { + @Test + void testRegisterAndUnregister() { + PlayerMock player = server.addPlayer(); + SpawnTeleportTask task = new SpawnTeleportTask(plugin, player, 5); + Location loc = player.getLocation(); + SpawnTaskManager registry = plugin.getManagerFactory().getSpawnTaskManager(); + assertEquals(Result.SUCCESS, registry.register(player.getUniqueId(), loc, task)); + assertEquals(Result.SUCCESS, registry.unregister(player.getUniqueId())); + } + + @Test + void testMovementCancelsTeleport() { + PlayerMock player = server.addPlayer(); + SpawnTeleportTask task = new SpawnTeleportTask(plugin, player, 5); + Location start = player.getLocation(); + + task.start(); + + Location newLoc = start.clone().add(20, 0, 0); + player.simulatePlayerMove(newLoc); + + server.getScheduler().performTicks(20 * 5); + Location spawn = plugin.getUtils().getSpawn(); + System.out.println(newLoc); + System.out.println(player.getLocation()); + System.out.println(spawn); + assertNotEquals(spawn, player.getLocation(), "Teleport should have been cancelled"); + } + + @Test + void testNonMovementDoesNotCancel() { + PlayerMock player = server.addPlayer(); + SpawnTeleportTask task = new SpawnTeleportTask(plugin, player, 2); + Location start = player.getLocation(); + + SpawnTaskManager registry = plugin.getManagerFactory().getSpawnTaskManager(); + + registry.register(player.getUniqueId(), start, task); + task.start(); + + PlayerMoveEvent event = new PlayerMoveEvent(player, start, start); + plugin.getServer().getPluginManager().callEvent(event); + + server.getScheduler().performTicks(20 * 2); + + assertEquals(plugin.getUtils().getSpawn(), player.getLocation(), "Teleport should NOT have been cancelled"); + } +} diff --git a/src/test/java/me/calrl/hubbly/listeners/world/WorldEventListenersTest.java b/src/test/java/me/calrl/hubbly/listeners/world/WorldEventListenersTest.java new file mode 100644 index 0000000..27c6535 --- /dev/null +++ b/src/test/java/me/calrl/hubbly/listeners/world/WorldEventListenersTest.java @@ -0,0 +1,206 @@ +package me.calrl.hubbly.listeners.world; + +import be.seeseemelk.mockbukkit.Coordinate; +import be.seeseemelk.mockbukkit.MockBukkit; +import be.seeseemelk.mockbukkit.ServerMock; +import be.seeseemelk.mockbukkit.WorldMock; +import be.seeseemelk.mockbukkit.entity.PlayerMock; +import me.calrl.hubbly.Hubbly; +import me.calrl.hubbly.enums.Permissions; +import me.calrl.hubbly.enums.PluginKeys; +import me.calrl.hubbly.listeners.world.WorldEventListeners; +import me.calrl.hubbly.managers.DisabledWorlds; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.block.*; +import org.bukkit.event.entity.*; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.weather.ThunderChangeEvent; +import org.bukkit.event.weather.WeatherChangeEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.permissions.PermissionAttachment; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class WorldEventListenersTest { + + private ServerMock server; + private Hubbly plugin; + private WorldEventListeners listener; + private PlayerMock player; + private WorldMock world; + private WorldMock disabledWorld; + + @BeforeEach + public void setUp() { + server = MockBukkit.getOrCreateMock(); + plugin = MockBukkit.load(Hubbly.class); + listener = new WorldEventListeners(plugin); + + // Create worlds + world = server.addSimpleWorld("world"); + disabledWorld = server.addSimpleWorld("disabled_world"); + + // Setup player in regular world + player = server.addPlayer(); + player.teleport(new Location(world, 0, 0, 0)); + + // Register listener + server.getPluginManager().registerEvents(listener, plugin); + + // Mock disabled worlds manager + DisabledWorlds disabledWorlds = plugin.getDisabledWorldsManager(); + World disabledWorld = server.getWorld("disabled_world"); + disabledWorlds.addWorld(disabledWorld); + } + + @Test + public void testOnBlockPlace_CancelledWhenInDisabledWorld() { + player.teleport(new Location(disabledWorld, 0, 0, 0)); + + // Create a proper block state for the replaced block + Block replacedBlock = disabledWorld.getBlockAt(0, 0, 0); + BlockState replacedBlockState = replacedBlock.getState(); + + Block placedAgainst = disabledWorld.getBlockAt(0, 1, 0); + boolean canBuild = true; + + BlockPlaceEvent event = new BlockPlaceEvent( + replacedBlock, // The block that was placed + replacedBlockState, // The state of the block being replaced + placedAgainst, // The block against which it was placed + new ItemStack(Material.STONE), // The item being placed + player, // The player placing it + canBuild // Whether the player can build + ); + + server.getPluginManager().callEvent(event); + assertTrue(event.isCancelled()); + } + + @Test + public void testOnBlockPlace_BypassPermission() { + player.addAttachment(plugin, "hubbly.bypass.place", true); + BlockPlaceEvent event = new BlockPlaceEvent( + world.getBlockAt(0, 0, 0), + null, + null, + new ItemStack(Material.STONE), + player, + true + ); + + server.getPluginManager().callEvent(event); + assertFalse(event.isCancelled()); + } + + @Test + public void testOnBlockPlace_CancelledWhenConfigured() { + plugin.getConfig().set("cancel_events.block_place", true); + BlockPlaceEvent event = new BlockPlaceEvent( + world.getBlockAt(0, 0, 0), + null, + null, + new ItemStack(Material.STONE), + player, + true + ); + + server.getPluginManager().callEvent(event); + assertTrue(event.isCancelled()); + } + + @Test + public void testOnBlockBreak_CancelledWhenInDisabledWorld() { + player.teleport(new Location(disabledWorld, 0, 0, 0)); + + BlockBreakEvent event = new BlockBreakEvent( + world.getBlockAt(0, 0, 0), + player + ); + + server.getPluginManager().callEvent(event); + assertTrue(event.isCancelled()); + } + + @Test + public void testOnBlockBreak_BypassPermission() { + PermissionAttachment attachment = player.addAttachment(plugin, "hubbly.bypass.break", true); + BlockBreakEvent event = new BlockBreakEvent( + world.getBlockAt(0, 0, 0), + player + ); + + server.getPluginManager().callEvent(event); + assertFalse(event.isCancelled()); + + player.removeAttachment(attachment); + } + + @Test + public void testOnBlockBreak_CancelledWhenConfigured() { + plugin.getConfig().set("cancel_events.block_break", true); + BlockBreakEvent event = new BlockBreakEvent( + world.getBlockAt(0, 0, 0), + player + ); + + server.getPluginManager().callEvent(event); + assertTrue(event.isCancelled()); + } + + @Test + public void testCancelDamage_CancelledWhenInDisabledWorld() { + player.teleport(new Location(disabledWorld, 0, 0, 0)); + + EntityDamageEvent event = new EntityDamageEvent( + player, + EntityDamageEvent.DamageCause.FALL, + 10.0 + ); + + server.getPluginManager().callEvent(event); + assertTrue(event.isCancelled()); + } + + @Test + public void testCancelDamage_BypassPermission() { + player.addAttachment(plugin, "hubbly.bypass.damage", true); + EntityDamageEvent event = new EntityDamageEvent( + player, + EntityDamageEvent.DamageCause.FALL, + 10.0 + ); + + server.getPluginManager().callEvent(event); + assertFalse(event.isCancelled()); + } + + @Test + public void testCancelDamage_CancelledWhenConfigured() { + plugin.getConfig().set("cancel_events.damage", true); + + EntityDamageEvent event = new EntityDamageEvent( + player, + EntityDamageEvent.DamageCause.FALL, + 10.0 + ); + + + server.getPluginManager().callEvent(event); + assertTrue(event.isCancelled()); + } +} diff --git a/src/test/java/me/calrl/hubbly/managers/DisabledWorldsTest.java b/src/test/java/me/calrl/hubbly/managers/DisabledWorldsTest.java new file mode 100644 index 0000000..24ac904 --- /dev/null +++ b/src/test/java/me/calrl/hubbly/managers/DisabledWorldsTest.java @@ -0,0 +1,86 @@ +package me.calrl.hubbly.managers; + +import be.seeseemelk.mockbukkit.MockBukkit; +import be.seeseemelk.mockbukkit.ServerMock; +import be.seeseemelk.mockbukkit.WorldMock; +import com.sun.source.tree.AssertTree; +import me.calrl.hubbly.Hubbly; +import me.calrl.hubbly.PluginTestBase; +import org.bukkit.World; +import org.bukkit.entity.Wolf; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class DisabledWorldsTest extends PluginTestBase { + + @BeforeEach + public void setup() { + + server.addSimpleWorld("world"); + server.addSimpleWorld("world_nether"); + server.addSimpleWorld("world_the_end"); + } + + @Test + public void worldsExist() { + List worlds = server.getWorlds(); + + World world = server.getWorld("world"); + World nether = server.getWorld("world_nether"); + World end = server.getWorld("world_the_end"); + + assertTrue(worlds.contains(world)); + assertTrue(worlds.contains(nether)); + assertTrue(worlds.contains(end)); + } + + @Test + public void addsToDisabledWorlds() { + + DisabledWorlds disabledWorlds = plugin.getDisabledWorldsManager(); + disabledWorlds.clear(); + + World world = server.getWorld("world"); + disabledWorlds.addWorld(world); + + assertTrue(disabledWorlds.inDisabledWorld(world)); + assertTrue(disabledWorlds.getDisabledWorlds().contains(world)); + } + + @Test + public void disabledWorldsTest() { + DisabledWorlds disabledWorlds = plugin.getDisabledWorldsManager(); + disabledWorlds.clear(); + + plugin.getConfig().set("disabled-worlds", List.of("world_nether", "world_the_end")); + plugin.saveConfig(); + + disabledWorlds.setDisabledWorlds(); + + System.out.println(disabledWorlds.getDisabledWorldNames()); + + assertTrue(disabledWorlds.getDisabledWorldNames().contains("world_nether")); + assertTrue(disabledWorlds.getDisabledWorldNames().contains("world_the_end")); + } + + @Test + public void disabledWorldsInvertedTest() { + DisabledWorlds disabledWorlds = plugin.getDisabledWorldsManager(); + disabledWorlds.clear(); + + plugin.getConfig().set("disabled-worlds", List.of("world_nether", "world_the_end")); + plugin.getConfig().set("invert", true); + plugin.saveConfig(); + + disabledWorlds.setDisabledWorlds(); + + System.out.println(disabledWorlds.getDisabledWorldNames()); + + assertTrue(disabledWorlds.getDisabledWorldNames().contains("world")); + } +} diff --git a/src/test/java/me/calrl/hubbly/tasks/spawn/SpawnTeleportTaskTests.java b/src/test/java/me/calrl/hubbly/tasks/spawn/SpawnTeleportTaskTests.java new file mode 100644 index 0000000..92941b0 --- /dev/null +++ b/src/test/java/me/calrl/hubbly/tasks/spawn/SpawnTeleportTaskTests.java @@ -0,0 +1,54 @@ +package me.calrl.hubbly.tasks.spawn; + +import be.seeseemelk.mockbukkit.entity.PlayerMock; +import me.calrl.hubbly.PluginTestBase; +import me.calrl.hubbly.enums.Result; +import me.calrl.hubbly.managers.SpawnTaskManager; +import org.bukkit.Location; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class SpawnTeleportTaskTests extends PluginTestBase { + + @Test + void testStartReturnsSuccess() { + PlayerMock player = server.addPlayer(); + SpawnTeleportTask task = new SpawnTeleportTask(plugin, player, 5); + Result result = task.start(); + + assertEquals(Result.SUCCESS, result); + assertSame(player, task.getPlayer()); + assertNotNull(task.getTask()); + } + + @Test + void testCancelUnregistersAndReturnsSuccess() { + PlayerMock player = server.addPlayer(); + SpawnTeleportTask task = new SpawnTeleportTask(plugin, player, 5); + task.start(); + + Result result = task.cancel(); + + assertEquals(Result.SUCCESS, result); + + SpawnTaskManager registry = plugin.getManagerFactory().getSpawnTaskManager(); + assertDoesNotThrow(() -> registry.unregister(player.getUniqueId())); + } + + @Test + void testTeleportAfterDelay() { + PlayerMock player = server.addPlayer(); + Location start = player.getLocation(); + Location spawn = plugin.getUtils().getSpawn(); + long timer = 2; + + SpawnTeleportTask task = new SpawnTeleportTask(plugin, player, timer); + task.start(); + + + server.getScheduler().performTicks(20 * timer); + + assertEquals(spawn, player.getLocation(), "Player should have been teleported to spawn"); + } +} diff --git a/src/test/resources/config.yml b/src/test/resources/config.yml index 256ee68..6ddc16c 100644 --- a/src/test/resources/config.yml +++ b/src/test/resources/config.yml @@ -1,8 +1,9 @@ -debug: true +debug: false prefix: '&e&lHubbly &7&l>&r' check_for_update: true # Send message if no update? notify_on_no_update: false +default_language: en #----------------# # Disabled Worlds # @@ -47,18 +48,22 @@ playervisibility: movementitems: enderbow: - enabled: true + material: BOW # <- do not change this + enabled: false name: "<#A020F0>Enderbow" cooldown: 3 trident: + material: TRIDENT # <- do not change this enabled: true name: "<#40E0D0>Trident" cooldown: 3 grappling_hook: + material: FISHING_ROD # <- do not change this enabled: true name: "<#FFFF00>Grappling Hook" cooldown: 3 aote: + material: DIAMOND_SWORD # <- you can change this enabled: true name: "<#2d0043>Aspect of the End" cooldown: 1 @@ -141,9 +146,9 @@ anti_world_download: enabled: true notify_admin: true -#------------# +#-----------------# # CHAT MANAGEMENT # -#------------# +#-----------------# lock_chat: false @@ -181,30 +186,3 @@ announcements: - 'This is a second announcement' - 'Goodbye' -#----------# -# MESSAGES # -#----------# - -messages: - no_console: "Only players can use this command!" - no_permission_command: "You do not have permission to use this command!" - no_permission_use: "You do not have permission to use this!" - reload: "Reloaded Hubbly plugin" - fly: - enable: "Flight mode enabled." - disable: "Flight mode disabled." - no_fly_enabled: "Flight is disabled in config" - blocked_command: 'Unknown command. Type "/help" for help' - blocked_message: 'Please do not use that word!' - success: "Success!" - console_error: "Error. Please check console" - - # No PAPI support, only %player% placeholder to get the person who locked the chat. - chat_locked: "Chat has been locked by %player%" - chat_unlocked: "Chat has been unlocked by %player%" - -update: - new_update: "An update is available! Hubbly %new% can be downloaded on SpigotMC, you are on %current%" - no_update: "Hubbly %current% is up to date" - error: "Could not check for a new version..." - diff --git a/src/test/resources/items.yml b/src/test/resources/items.yml index 20d6fd8..c25078a 100644 --- a/src/test/resources/items.yml +++ b/src/test/resources/items.yml @@ -1,21 +1,26 @@ # Custom Items that you make myself, please follow the format. # To get these items use /hubbly give -# For item1, I would use /hubbly give item1 +# For compass, I would use /hubbly give compass items: - item1: - name: '' - type: REDSTONE_BLOCK + compass: + name: "&cCompass" + material: COMPASS + glow: true lore: - - 'line 1' - - 'line 2' + - "&7Right click me to open" + - "&7the server selector!" actions: - - '[PLAYER] spawn' - - '[CONSOLE] broadcast item1' + - "[MENU] selector" + socials: + name: "Socials" + material: PLAYER_HEAD + url: http://textures.minecraft.net/texture/355e2dc46399b7b9275221fcdc87c66e58d0d3044dcf62af0465122c1cd7e0bc + actions: + - "[MENU] socials" shop: - name: '&aShop' - type: EMERALD + name: "&aShop" + material: EMERALD_BLOCK lore: - - '&7Opens the shop' + - "&7Opens the shop" actions: - - '[PLAYER] buy' - + - "[PLAYER] buy" diff --git a/src/test/resources/menus/selector.yml b/src/test/resources/menus/selector.yml new file mode 100644 index 0000000..dd9cdeb --- /dev/null +++ b/src/test/resources/menus/selector.yml @@ -0,0 +1,64 @@ +# PLAYER HEADS +# You can have player heads, using player names, URLs or HeadDatabase IDs. +# Examples +# Player +# material: PLAYER_HEAD +# texture: player +# +# URL +# material: PLAYER_HEAD +# texture: +# +# HeadDatabase +# material: PLAYER_HEAD +# hdb: + +# AMOUNT +# You can change the amount using: +# amount: 3 + +# LEATHER ARMOR +# You can have different color LeatherArmor. +# Example +# #8ad592 color +# material: LEATHER_CHESTPLATE +# color: 8ad592 <- without the hashtag (#) + +title: "&cServer Selector" +size: 36 +items: + survival: + material: APPLE + name: "<#CCFFDD>Survival Server" + amount: 3 + url: http://textures.minecraft.net/texture/355e2dc46399b7b9275221fcdc87c66e58d0d3044dcf62af0465122c1cd7e0bc + model_data: 10001 # <- Model Data ID + slot: 12 # <- 0-based index + lore: + - "&aJoin the Survival Server!" + actions: + - "[BUNGEE] survival" + creative: + material: PLAYER_HEAD + texture: http://textures.minecraft.net/texture/bcf2105bb737638833033dd8244071e75870e2e11c2617e542e8924fb2b90180 + name: "&cCreative Server" + slot: 14 + lore: + - "&aJoin the Survival Server!" + actions: + - "[BUNGEE] creative" + factions: + material: LEATHER_CHESTPLATE + color: 8ad592 + name: "&cFactions Server" + slot: 22 + lore: + - "&aJoin the Survival Server!" + actions: + - "[BUNGEE] factions" + fill: + slot: -1 # <- use -1 to use as fill item + material: BLACK_STAINED_GLASS_PANE + name: " " + actions: + - "[CLOSE]" diff --git a/src/test/resources/menus/socials.yml b/src/test/resources/menus/socials.yml new file mode 100644 index 0000000..93b4063 --- /dev/null +++ b/src/test/resources/menus/socials.yml @@ -0,0 +1,28 @@ +title: "&6Socials" +size: 9 +items: + discord: + material: PLAYER_HEAD + name: "&3Discord Server" + url: http://textures.minecraft.net/texture/7873c12bffb5251a0b88d5ae75c7247cb39a75ff1a81cbe4c8a39b311ddeda + slot: 3 + lore: + - "&aJoin the Discord Server!" + actions: + - "[LINK] Click me for the discord;Discord link;discord.com/invite" + tiktok: + material: PLAYER_HEAD + url: http://textures.minecraft.net/texture/2786dc9d65c3b7983e8bb6af588fac92f33720c723e0d29f8b74151344a648a1 + name: "&cTiktok" + slot: 5 + lore: + - "&aFollow me on TikTok!" + actions: + - "[LINK] Click me to open TikTok!;TikTok link;tiktok.com" + + fill: + slot: -1 + material: BLACK_STAINED_GLASS_PANE + name: " " + actions: + - "[CLOSE]" diff --git a/src/test/resources/serverselector.yml b/src/test/resources/serverselector.yml deleted file mode 100644 index bdb3676..0000000 --- a/src/test/resources/serverselector.yml +++ /dev/null @@ -1,21 +0,0 @@ -selector: - enabled: true - material: COMPASS - name: '&6Server Selector' - gui: - size: 27 # Number of slots in the GUI - title: Server Selector # Title displayed in the GUI - items: - example_item: # Key for this item - material: DIAMOND # - name: '%player_name%''s Server' # Display name of the item with placeholder - slot: 5 - lore: # Lore for the item - - "This is line 1" - - "This is line 2 with %player_name%" - actions: - - '[PLAYER] kit' - fill: - name: " " - type: "BLACK_STAINED_GLASS_PANE" -