diff --git a/README.md b/README.md index 6132262..a3e662f 100644 --- a/README.md +++ b/README.md @@ -4,26 +4,27 @@ Extras is a Bukkit plugin that that adds extra functionality to the Kaboom serve ## Commands -| Command | Aliases | Permission | Description | -|-----------------------|----------------------------------------------|-----------------------------|---------------------------------------------------------------| -| /broadcastminimessage | /broadcastmm, /bcmm | extras.broadcastminimessage | Broadcasts a deserialized MiniMessage component | -| /broadcastraw | /bcraw, /tellraw | extras.broadcastraw | Broadcasts raw text to the server | -| /broadcastvanilla | /bcv | extras.broadcastvanilla | Broadcasts text in vanilla style | -| /clearchat | /cc | extras.clearchat | Clears messages from the chat | -| /console | | extras.console | Broadcasts a message as the console | -| /destroyentities | /de | extras.destroyentities | Destroys all entities in every world | -| /enchantall | | extras.enchantall | Adds every enchantment to a held item | -| /getjson | /gj, /gmm | extras.getjson | Gets the JSON of a deserialized MiniMessage/legacy component | -| /jumpscare | /scare | extras.jumpscare | Scares a player | -| /kaboom | | extras.kaboom | I wonder... | -| /ping | /ms, /delay | extras.ping | Gets your ping | -| /prefix | /rank, /tag | extras.prefix | Changes your tag | -| /pumpkin | | extras.pumpkin | Places a pumpkin on a player's head | -| /serverinfo | /specs | extras.serverinfo | Shows detailed server information | -| /skin | | extras.skin | Changes your skin | -| /spawn | | extras.spawn | Teleports you to spawn | -| /spidey | | extras.spidey | Annoying little spider... | -| /username | | extras.username | Changes your username on the server | +| Command | Aliases | Permission | Description | +|-----------------------|---------------------|-----------------------------|---------------------------------------------------------| +| /broadcastminimessage | /broadcastmm, /bcmm | extras.broadcastminimessage | Broadcasts a deserialized MiniMessage component | +| /broadcastraw | /bcraw, /tellraw | extras.broadcastraw | Broadcasts raw text to the server | +| /broadcastvanilla | /bcv | extras.broadcastvanilla | Broadcasts text in vanilla style | +| /clearchat | /cc | extras.clearchat | Clears messages from the chat | +| /console | | extras.console | Broadcasts a message as the console | +| /destroyentities | /de | extras.destroyentities | Destroys all entities in every world | +| /enchantall | | extras.enchantall | Adds every enchantment to a held item | +| /getjson | /gj | extras.getjson | Gets the JSON of a deserialized legacy component | +| /getjsonmm | /gmm | extras.getjsonmm | Gets the JSON of a deserialized MiniMessage component | +| /jumpscare | /scare | extras.jumpscare | Scares a player | +| /kaboom | | extras.kaboom | I wonder... | +| /ping | /ms, /delay | extras.ping | Gets your ping | +| /prefix | /rank, /tag | extras.prefix | Changes your tag | +| /pumpkin | | extras.pumpkin | Places a pumpkin on a player's head | +| /serverinfo | /specs | extras.serverinfo | Shows detailed server information | +| /skin | | extras.skin | Changes your skin | +| /spawn | | extras.spawn | Teleports you to spawn | +| /spidey | | extras.spidey | Annoying little spider... | +| /username | | extras.username | Changes your username on the server | ## Compiling diff --git a/pom.xml b/pom.xml index 8519cc4..e98f3b3 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ io.papermc.paper paper-api - 1.18.2-R0.1-SNAPSHOT + 1.19.4-R0.1-SNAPSHOT provided diff --git a/src/main/java/pw/kaboom/extras/Main.java b/src/main/java/pw/kaboom/extras/Main.java index 2aafc53..f855b7f 100644 --- a/src/main/java/pw/kaboom/extras/Main.java +++ b/src/main/java/pw/kaboom/extras/Main.java @@ -1,50 +1,27 @@ package pw.kaboom.extras; -import java.io.File; -import java.util.Collections; import org.bukkit.WorldCreator; import org.bukkit.WorldType; import org.bukkit.block.BlockFace; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.java.JavaPlugin; -import pw.kaboom.extras.commands.CommandBroadcastMM; -import pw.kaboom.extras.commands.CommandBroadcastVanilla; -import pw.kaboom.extras.commands.CommandClearChat; -import pw.kaboom.extras.commands.CommandConsole; -import pw.kaboom.extras.commands.CommandDestroyEntities; -import pw.kaboom.extras.commands.CommandEnchantAll; -import pw.kaboom.extras.commands.CommandGetJSON; -import pw.kaboom.extras.commands.CommandJumpscare; -import pw.kaboom.extras.commands.CommandKaboom; -import pw.kaboom.extras.commands.CommandPing; -import pw.kaboom.extras.commands.CommandPrefix; -import pw.kaboom.extras.commands.CommandPumpkin; -import pw.kaboom.extras.commands.CommandServerInfo; -import pw.kaboom.extras.commands.CommandSkin; -import pw.kaboom.extras.commands.CommandSpawn; -import pw.kaboom.extras.commands.CommandSpidey; -import pw.kaboom.extras.commands.CommandTellraw; -import pw.kaboom.extras.commands.CommandUsername; +import pw.kaboom.extras.commands.*; import pw.kaboom.extras.modules.block.BlockCheck; import pw.kaboom.extras.modules.block.BlockPhysics; import pw.kaboom.extras.modules.entity.EntityExplosion; import pw.kaboom.extras.modules.entity.EntityKnockback; import pw.kaboom.extras.modules.entity.EntitySpawn; import pw.kaboom.extras.modules.entity.EntityTeleport; -import pw.kaboom.extras.modules.player.PlayerChat; -import pw.kaboom.extras.modules.player.PlayerCommand; -import pw.kaboom.extras.modules.player.PlayerConnection; -import pw.kaboom.extras.modules.player.PlayerDamage; -import pw.kaboom.extras.modules.player.PlayerInteract; -import pw.kaboom.extras.modules.player.PlayerPrefix; -import pw.kaboom.extras.modules.player.PlayerRecipe; -import pw.kaboom.extras.modules.player.PlayerTeleport; +import pw.kaboom.extras.modules.player.*; import pw.kaboom.extras.modules.server.ServerCommand; import pw.kaboom.extras.modules.server.ServerGameRule; import pw.kaboom.extras.modules.server.ServerTabComplete; import pw.kaboom.extras.modules.server.ServerTick; +import java.io.File; +import java.util.Collections; + public final class Main extends JavaPlugin { private File prefixConfigFile; private FileConfiguration prefixConfig; @@ -80,6 +57,7 @@ public final class Main extends JavaPlugin { this.getCommand("destroyentities").setExecutor(new CommandDestroyEntities()); this.getCommand("enchantall").setExecutor(new CommandEnchantAll()); this.getCommand("getjson").setExecutor(new CommandGetJSON()); + this.getCommand("getjsonmm").setExecutor(new CommandGetJSONMM()); this.getCommand("jumpscare").setExecutor(new CommandJumpscare()); this.getCommand("kaboom").setExecutor(new CommandKaboom()); this.getCommand("ping").setExecutor(new CommandPing()); diff --git a/src/main/java/pw/kaboom/extras/commands/CommandBroadcastMM.java b/src/main/java/pw/kaboom/extras/commands/CommandBroadcastMM.java index 3bf4c7b..ab293c9 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandBroadcastMM.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandBroadcastMM.java @@ -10,7 +10,7 @@ import org.bukkit.command.CommandSender; import javax.annotation.Nonnull; -public class CommandBroadcastMM implements CommandExecutor { +public final class CommandBroadcastMM implements CommandExecutor { private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); public boolean onCommand(final @Nonnull CommandSender sender, diff --git a/src/main/java/pw/kaboom/extras/commands/CommandBroadcastVanilla.java b/src/main/java/pw/kaboom/extras/commands/CommandBroadcastVanilla.java index 6ea160a..78ea956 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandBroadcastVanilla.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandBroadcastVanilla.java @@ -2,14 +2,23 @@ package pw.kaboom.extras.commands; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.ChatColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; import javax.annotation.Nonnull; +import java.util.Collection; public final class CommandBroadcastVanilla implements CommandExecutor { + private static final LegacyComponentSerializer LEGACY_COMPONENT_SERIALIZER = + LegacyComponentSerializer + .legacyAmpersand(); + public boolean onCommand(final @Nonnull CommandSender sender, final @Nonnull Command command, final @Nonnull String label, @@ -21,8 +30,29 @@ public final class CommandBroadcastVanilla implements CommandExecutor { return true; } - Command.broadcastCommandMessage(sender, ChatColor.translateAlternateColorCodes( - '&', String.join(" ", args))); + final Component senderName = sender.name(); + final String input = String.join(" ", args); + final Component component = LEGACY_COMPONENT_SERIALIZER.deserialize(input); + final Component broadcastComponent = Component.translatable("chat.type.admin") + .decorate(TextDecoration.ITALIC) + .color(NamedTextColor.GRAY) + .args(senderName, component); + + sender.sendMessage(component); + + final Collection onlinePlayers = Bukkit.getOnlinePlayers(); + + for (final Player onlinePlayer : onlinePlayers) { + if (onlinePlayer.equals(sender)) { + continue; + } + + onlinePlayer.sendMessage(broadcastComponent); + } + + final ConsoleCommandSender consoleCommandSender = Bukkit.getConsoleSender(); + consoleCommandSender.sendMessage(broadcastComponent); + return true; } } diff --git a/src/main/java/pw/kaboom/extras/commands/CommandEnchantAll.java b/src/main/java/pw/kaboom/extras/commands/CommandEnchantAll.java index ec04c5f..70e64e2 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandEnchantAll.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandEnchantAll.java @@ -5,7 +5,6 @@ import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -17,13 +16,12 @@ public final class CommandEnchantAll implements CommandExecutor { final @Nonnull Command command, final @Nonnull String label, final String[] args) { - if (sender instanceof ConsoleCommandSender) { + if (!(sender instanceof final Player player)) { sender.sendMessage(Component .text("Command has to be run by a player")); return true; } - final Player player = (Player) sender; final ItemStack item = player.getInventory().getItemInMainHand(); if (Material.AIR.equals(item.getType())) { diff --git a/src/main/java/pw/kaboom/extras/commands/CommandGetJSON.java b/src/main/java/pw/kaboom/extras/commands/CommandGetJSON.java index d9661b0..e92c5a9 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandGetJSON.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandGetJSON.java @@ -1,6 +1,5 @@ package pw.kaboom.extras.commands; -import javax.annotation.Nonnull; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.NamedTextColor; @@ -10,7 +9,9 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -public class CommandGetJSON implements CommandExecutor { +import javax.annotation.Nonnull; + +public final class CommandGetJSON implements CommandExecutor { public boolean onCommand(final @Nonnull CommandSender sender, final @Nonnull Command command, final @Nonnull String label, diff --git a/src/main/java/pw/kaboom/extras/commands/CommandGetJSONMM.java b/src/main/java/pw/kaboom/extras/commands/CommandGetJSONMM.java new file mode 100644 index 0000000..1f53abe --- /dev/null +++ b/src/main/java/pw/kaboom/extras/commands/CommandGetJSONMM.java @@ -0,0 +1,40 @@ +package pw.kaboom.extras.commands; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + +import javax.annotation.Nonnull; + +public final class CommandGetJSONMM implements CommandExecutor { + public boolean onCommand(final @Nonnull CommandSender sender, + final @Nonnull Command command, + final @Nonnull String label, + final String[] args) { + if (args.length == 0) { + sender.sendMessage(Component + .text("Usage: /" + label + " ", NamedTextColor.RED)); + return true; + } + + final String message = String.join(" ", args); + Component createdComponent = MiniMessage.miniMessage() + .deserialize(message); + + String asJson = GsonComponentSerializer.gson() + .serialize(createdComponent); + + Component feedback = Component.empty() + .append(Component.text("Your component as JSON (click to copy): ")) + .append(Component.text(asJson, NamedTextColor.GREEN)) + .clickEvent(ClickEvent.copyToClipboard(asJson)); + + sender.sendMessage(feedback); + return true; + } +} diff --git a/src/main/java/pw/kaboom/extras/commands/CommandKaboom.java b/src/main/java/pw/kaboom/extras/commands/CommandKaboom.java index ede8fdc..2a8a22c 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandKaboom.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandKaboom.java @@ -19,7 +19,12 @@ public final class CommandKaboom implements CommandExecutor { final @Nonnull Command command, final @Nonnull String label, final String[] args) { - final Player player = (Player) sender; + if (!(sender instanceof final Player player)) { + sender.sendMessage(Component + .text("Command has to be run by a player")); + return true; + } + boolean explode = ThreadLocalRandom.current().nextBoolean(); if (explode) { diff --git a/src/main/java/pw/kaboom/extras/commands/CommandPrefix.java b/src/main/java/pw/kaboom/extras/commands/CommandPrefix.java index e62c907..c89d0e4 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandPrefix.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandPrefix.java @@ -1,15 +1,15 @@ package pw.kaboom.extras.commands; -import javax.annotation.Nonnull; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import pw.kaboom.extras.modules.player.PlayerPrefix; +import javax.annotation.Nonnull; + public final class CommandPrefix implements CommandExecutor { @@ -17,14 +17,12 @@ public final class CommandPrefix implements CommandExecutor { final @Nonnull Command cmd, final @Nonnull String label, final String[] args) { - if (sender instanceof ConsoleCommandSender) { + if (!(sender instanceof final Player player)) { sender.sendMessage(Component .text("Command has to be run by a player")); return true; } - final Player player = (Player) sender; - if (args.length == 0) { player.sendMessage(Component .text("Usage: /" + label + " ", diff --git a/src/main/java/pw/kaboom/extras/commands/CommandSkin.java b/src/main/java/pw/kaboom/extras/commands/CommandSkin.java index 204f7a2..09f6fd6 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandSkin.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandSkin.java @@ -1,17 +1,16 @@ package pw.kaboom.extras.commands; -import java.util.HashMap; -import java.util.Map; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import pw.kaboom.extras.skin.SkinManager; import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; public final class CommandSkin implements CommandExecutor { private final Map lastUsedMillis = new HashMap<>(); @@ -21,13 +20,12 @@ public final class CommandSkin implements CommandExecutor { final @Nonnull Command command, final @Nonnull String label, final String[] args) { - if (sender instanceof ConsoleCommandSender) { + if (!(sender instanceof final Player player)) { sender.sendMessage(Component .text("Command has to be run by a player")); return true; } - final Player player = (Player) sender; final long millis = lastUsedMillis.getOrDefault(player, 0L); final long millisDifference = System.currentTimeMillis() - millis; diff --git a/src/main/java/pw/kaboom/extras/commands/CommandSpawn.java b/src/main/java/pw/kaboom/extras/commands/CommandSpawn.java index 6d9456f..c0b5b0e 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandSpawn.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandSpawn.java @@ -9,7 +9,6 @@ import org.bukkit.block.BlockFace; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import javax.annotation.Nonnull; @@ -19,13 +18,12 @@ public final class CommandSpawn implements CommandExecutor { final @Nonnull Command command, final @Nonnull String label, final String[] args) { - if (sender instanceof ConsoleCommandSender) { + if (!(sender instanceof final Player player)) { sender.sendMessage(Component .text("Command has to be run by a player")); return true; } - final Player player = (Player) sender; final World defaultWorld = Bukkit.getWorld("world"); final World world = (defaultWorld == null) ? Bukkit.getWorlds().get(0) : defaultWorld; final Location spawnLocation = world.getSpawnLocation(); diff --git a/src/main/java/pw/kaboom/extras/commands/CommandSpidey.java b/src/main/java/pw/kaboom/extras/commands/CommandSpidey.java index bb48e99..f2e1159 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandSpidey.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandSpidey.java @@ -6,7 +6,6 @@ import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import org.bukkit.util.BlockIterator; import org.bukkit.util.Vector; @@ -18,13 +17,12 @@ public final class CommandSpidey implements CommandExecutor { final @Nonnull Command command, final @Nonnull String label, final String[] args) { - if (sender instanceof ConsoleCommandSender) { + if (!(sender instanceof final Player player)) { sender.sendMessage(Component .text("Command has to be run by a player")); return true; } - final Player player = (Player) sender; final World world = player.getWorld(); final Vector start = player.getEyeLocation().toVector(); final Vector direction = player.getEyeLocation().getDirection(); diff --git a/src/main/java/pw/kaboom/extras/commands/CommandUsername.java b/src/main/java/pw/kaboom/extras/commands/CommandUsername.java index 4c9de77..f42804a 100644 --- a/src/main/java/pw/kaboom/extras/commands/CommandUsername.java +++ b/src/main/java/pw/kaboom/extras/commands/CommandUsername.java @@ -1,8 +1,6 @@ package pw.kaboom.extras.commands; import com.destroystokyo.paper.profile.PlayerProfile; -import java.util.HashMap; -import java.util.Map; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; @@ -10,10 +8,11 @@ import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; public final class CommandUsername implements CommandExecutor { private final Map lastUsedMillis = new HashMap<>(); @@ -23,13 +22,12 @@ public final class CommandUsername implements CommandExecutor { final @Nonnull Command command, final @Nonnull String label, final String[] args) { - if (sender instanceof ConsoleCommandSender) { + if (!(sender instanceof final Player player)) { sender.sendMessage(Component .text("Command has to be run by a player")); return true; } - final Player player = (Player) sender; final String nameColor = ChatColor.translateAlternateColorCodes( '&', String.join(" ", args)); final String name = nameColor.substring(0, Math.min(16, nameColor.length())); @@ -56,7 +54,7 @@ public final class CommandUsername implements CommandExecutor { } for (Player other : Bukkit.getOnlinePlayers()) { - if (!other.getName().equals(name)) continue; + if (!other.getName().equalsIgnoreCase(name)) continue; player.sendMessage(Component .text("A player with that username is already logged in.")); diff --git a/src/main/java/pw/kaboom/extras/modules/player/PlayerChat.java b/src/main/java/pw/kaboom/extras/modules/player/PlayerChat.java index b898478..89052d3 100644 --- a/src/main/java/pw/kaboom/extras/modules/player/PlayerChat.java +++ b/src/main/java/pw/kaboom/extras/modules/player/PlayerChat.java @@ -2,18 +2,24 @@ package pw.kaboom.extras.modules.player; import io.papermc.paper.chat.ChatRenderer; import io.papermc.paper.event.player.AsyncChatEvent; -import java.io.IOException; -import java.util.UUID; -import javax.annotation.Nonnull; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.TextReplacementConfig; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import javax.annotation.Nonnull; +import java.io.IOException; +import java.util.UUID; +import java.util.regex.Pattern; + public final class PlayerChat implements Listener { private static final PlayerChatRenderer CHAT_RENDERER = new PlayerChatRenderer(); @@ -39,6 +45,43 @@ public final class PlayerChat implements Listener { } public static class PlayerChatRenderer implements ChatRenderer { + private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = + TextReplacementConfig + .builder() + .match(Pattern + .compile("((https?://(ww(w|\\d)\\.)?|ww(w|\\d))[-a-zA-Z0-9@:%._+~#=]{1,256}" + + "\\.[a-zA-Z0-9]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*))")) + .replacement((b, c) -> { + if (c == null) { + return null; + } + + if (b.groupCount() < 1) { + return null; + } + + final String content = b.group(1); + final String url; + + /* + Minecraft doesn't accept "www.google.com" as a URL + in click events + */ + if (content.contains("://")) { + url = content; + } else { + url = "https://" + content; + } + + return Component.text(content, NamedTextColor.BLUE) + .decorate(TextDecoration.UNDERLINED) + .clickEvent(ClickEvent.openUrl(url)); + }) + .build(); + + private static final LegacyComponentSerializer LEGACY_COMPONENT_SERIALIZER = + LegacyComponentSerializer + .legacyAmpersand(); @Override public @Nonnull Component render(@Nonnull Player player, @@ -65,10 +108,12 @@ public final class PlayerChat implements Listener { .append(Component.text(":")) .append(Component.space()); - return newComponent.append(LegacyComponentSerializer - .legacyAmpersand() - .deserialize(message) - ); + final Component messageWithColorCodes = LEGACY_COMPONENT_SERIALIZER + .deserialize(message); + final Component completedMessage = messageWithColorCodes + .replaceText(URL_REPLACEMENT_CONFIG); + + return newComponent.append(completedMessage); } } } diff --git a/src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java b/src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java index a15df64..29887e6 100644 --- a/src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java +++ b/src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java @@ -1,9 +1,8 @@ package pw.kaboom.extras.modules.player; -import java.util.HashSet; -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; - +import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; +import com.destroystokyo.paper.profile.ProfileProperty; +import com.google.common.base.Charsets; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Server; @@ -11,26 +10,19 @@ import org.bukkit.World; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.player.AsyncPlayerPreLoginEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerKickEvent; -import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.*; import org.bukkit.event.player.PlayerLoginEvent.Result; -import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.java.JavaPlugin; - import org.spigotmc.event.player.PlayerSpawnLocationEvent; - -import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; -import com.destroystokyo.paper.profile.ProfileProperty; - -import com.google.common.base.Charsets; - import pw.kaboom.extras.Main; import pw.kaboom.extras.modules.server.ServerTabComplete; import pw.kaboom.extras.skin.SkinManager; +import pw.kaboom.extras.util.Utility; + +import java.util.HashSet; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; public final class PlayerConnection implements Listener { private static final FileConfiguration CONFIG = JavaPlugin.getPlugin(Main.class).getConfig(); @@ -50,8 +42,9 @@ public final class PlayerConnection implements Listener { @EventHandler void onAsyncPlayerPreLogin(final AsyncPlayerPreLoginEvent event) { - if (Bukkit.getPlayer(event.getName()) != null - && Bukkit.getPlayer(event.getName()).isOnline()) { + final Player player = Utility.getPlayerExactIgnoreCase(event.getName()); + + if (player != null) { event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, "A player with that username is already logged in"); } diff --git a/src/main/java/pw/kaboom/extras/modules/player/PlayerPrefix.java b/src/main/java/pw/kaboom/extras/modules/player/PlayerPrefix.java index ce35ed3..d67e59b 100644 --- a/src/main/java/pw/kaboom/extras/modules/player/PlayerPrefix.java +++ b/src/main/java/pw/kaboom/extras/modules/player/PlayerPrefix.java @@ -1,11 +1,5 @@ package pw.kaboom.extras.modules.player; -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.Bukkit; @@ -21,15 +15,22 @@ import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitScheduler; import pw.kaboom.extras.Main; -public class PlayerPrefix implements Listener { - private static final Main plugin = JavaPlugin.getPlugin(Main.class); - private static final File PREFIX_CONFIG_FILE = plugin.getPrefixConfigFile(); - private static final FileConfiguration PREFIX_CONFIG = plugin.getPrefixConfig(); - private static final FileConfiguration PLUGIN_CONFIGURATION = plugin.getConfig(); - private static final Component opTag; - private static final Component deOpTag; - private static final Map opMap = new HashMap<>(); - private static final Map displayNameMap = new HashMap<>(); +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public final class PlayerPrefix implements Listener { + private static final Main PLUGIN = JavaPlugin.getPlugin(Main.class); + private static final File PREFIX_CONFIG_FILE = PLUGIN.getPrefixConfigFile(); + private static final FileConfiguration PREFIX_CONFIG = PLUGIN.getPrefixConfig(); + private static final FileConfiguration PLUGIN_CONFIGURATION = PLUGIN.getConfig(); + private static final Component OP_TAG; + private static final Component DE_OP_TAG; + private static final Map OP_MAP = new HashMap<>(); + private static final Map DISPLAY_NAME_MAP = new HashMap<>(); static { final String legacyOpTag = PLUGIN_CONFIGURATION.getString("opTag"); @@ -39,14 +40,14 @@ public class PlayerPrefix implements Listener { throw new RuntimeException("Invalid plugin configuration!"); } - opTag = LegacyComponentSerializer.legacySection().deserialize(legacyOpTag); - deOpTag = LegacyComponentSerializer.legacySection().deserialize(legacyDeOpTag); + OP_TAG = LegacyComponentSerializer.legacySection().deserialize(legacyOpTag); + DE_OP_TAG = LegacyComponentSerializer.legacySection().deserialize(legacyDeOpTag); final BukkitScheduler scheduler = Bukkit.getScheduler(); - scheduler.runTaskTimerAsynchronously(plugin, PlayerPrefix::checkOpStatus, + scheduler.runTaskTimerAsynchronously(PLUGIN, PlayerPrefix::checkOpStatus, 0L, 1L); - scheduler.runTaskTimerAsynchronously(plugin, PlayerPrefix::checkDisplayNames, + scheduler.runTaskTimerAsynchronously(PLUGIN, PlayerPrefix::checkDisplayNames, 0L, 1L); } @@ -79,7 +80,7 @@ public class PlayerPrefix implements Listener { final String legacyPrefix = PREFIX_CONFIG.getString(stringifiedUUID); if (legacyPrefix == null) { - return player.isOp() ? opTag : deOpTag; + return player.isOp() ? OP_TAG : DE_OP_TAG; } return LegacyComponentSerializer.legacyAmpersand() @@ -88,7 +89,7 @@ public class PlayerPrefix implements Listener { } public static Component getDefaultPrefix(Player player) { - return player.isOp() ? opTag : deOpTag; + return player.isOp() ? OP_TAG : DE_OP_TAG; } private static void onUpdate(Player player) throws IOException { @@ -104,8 +105,8 @@ public class PlayerPrefix implements Listener { final Player player = event.getPlayer(); final boolean isOp = player.isOp(); - opMap.put(player, isOp); - displayNameMap.put(player, player.displayName()); + OP_MAP.put(player, isOp); + DISPLAY_NAME_MAP.put(player, player.displayName()); onUpdate(player); } @@ -113,8 +114,8 @@ public class PlayerPrefix implements Listener { public void onPlayerQuitEvent(PlayerQuitEvent event) { final Player player = event.getPlayer(); - opMap.remove(player); - displayNameMap.remove(player); + OP_MAP.remove(player); + DISPLAY_NAME_MAP.remove(player); } private static void checkOpStatus() { @@ -124,17 +125,17 @@ public class PlayerPrefix implements Listener { for (Player player : players) { final boolean isOp = player.isOp(); - if (!opMap.containsKey(player)) { + if (!OP_MAP.containsKey(player)) { return; } - final boolean storedOp = opMap.get(player); + final boolean storedOp = OP_MAP.get(player); if (isOp == storedOp) { continue; } - opMap.put(player, isOp); + OP_MAP.put(player, isOp); try { onUpdate(player); @@ -151,17 +152,17 @@ public class PlayerPrefix implements Listener { for (Player player : players) { final Component displayName = player.displayName(); - if (!displayNameMap.containsKey(player)) { + if (!DISPLAY_NAME_MAP.containsKey(player)) { return; } - final Component storedDisplayName = displayNameMap.get(player); + final Component storedDisplayName = DISPLAY_NAME_MAP.get(player); if (displayName.equals(storedDisplayName)) { continue; } - displayNameMap.put(player, displayName); + DISPLAY_NAME_MAP.put(player, displayName); try { onUpdate(player); diff --git a/src/main/java/pw/kaboom/extras/modules/server/ServerCommand.java b/src/main/java/pw/kaboom/extras/modules/server/ServerCommand.java index c264583..0bf3b9b 100644 --- a/src/main/java/pw/kaboom/extras/modules/server/ServerCommand.java +++ b/src/main/java/pw/kaboom/extras/modules/server/ServerCommand.java @@ -1,11 +1,5 @@ package pw.kaboom.extras.modules.server; -import java.util.Arrays; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.bukkit.block.CommandBlock; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; @@ -14,9 +8,14 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.server.ServerCommandEvent; import org.bukkit.plugin.java.JavaPlugin; - import pw.kaboom.extras.Main; +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public final class ServerCommand implements Listener { private static final Pattern AS_AT_PATTERN = Pattern.compile( "\\b(as|at|facing entity) @[ae]\\b"); @@ -45,6 +44,9 @@ public final class ServerCommand implements Listener { || "tm".equalsIgnoreCase(cmd) || "tp".equalsIgnoreCase(cmd) || "w".equalsIgnoreCase(cmd) + || "place".equalsIgnoreCase(cmd) + || "fillbiome".equalsIgnoreCase(cmd) + || "ride".equalsIgnoreCase(cmd) ); } @@ -102,6 +104,9 @@ public final class ServerCommand implements Listener { } for (int i = 1; i < arr.length; i++) { + if ("summon".equalsIgnoreCase(arr[i])) { + return "cancel"; + } if (!"run".equalsIgnoreCase(arr[i])) { continue; } @@ -117,7 +122,7 @@ public final class ServerCommand implements Listener { String.join(" ", executeCommand), true, depth + 1); if (result == null) { continue; - } else if (result == "cancel") { + } else if (result.equals("cancel")) { return "cancel"; } final String pureExecute = String.join( @@ -208,11 +213,6 @@ public final class ServerCommand implements Listener { // Do nothing } - if (command.contains("distance")) { - return command.replace("distance=", "]").replace("\"distance\"=", "]") - .replace("'distance'=", "]"); - } - return null; } diff --git a/src/main/java/pw/kaboom/extras/modules/server/ServerGameRule.java b/src/main/java/pw/kaboom/extras/modules/server/ServerGameRule.java index 7e816d8..22c7e8d 100644 --- a/src/main/java/pw/kaboom/extras/modules/server/ServerGameRule.java +++ b/src/main/java/pw/kaboom/extras/modules/server/ServerGameRule.java @@ -1,11 +1,10 @@ package pw.kaboom.extras.modules.server; +import io.papermc.paper.event.world.WorldGameRuleChangeEvent; import org.bukkit.GameRule; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import io.papermc.paper.event.world.WorldGameRuleChangeEvent; - public final class ServerGameRule implements Listener { @EventHandler void onGameRuleChange(final WorldGameRuleChangeEvent event) { @@ -14,7 +13,9 @@ public final class ServerGameRule implements Listener { if ((gameRule == GameRule.RANDOM_TICK_SPEED && Integer.parseInt(event.getValue()) > 6) || (event.getGameRule() == GameRule.SPAWN_RADIUS - && Integer.parseInt(event.getValue()) > 100)) { + && Integer.parseInt(event.getValue()) > 100) + || (event.getGameRule() == GameRule.COMMAND_MODIFICATION_BLOCK_LIMIT + && Integer.parseInt(event.getValue()) > 32768)) { event.setCancelled(true); } } diff --git a/src/main/java/pw/kaboom/extras/skin/response/ProfileResponse.java b/src/main/java/pw/kaboom/extras/skin/response/ProfileResponse.java index 70da361..521103d 100644 --- a/src/main/java/pw/kaboom/extras/skin/response/ProfileResponse.java +++ b/src/main/java/pw/kaboom/extras/skin/response/ProfileResponse.java @@ -1,20 +1,3 @@ package pw.kaboom.extras.skin.response; -public class ProfileResponse { - - public ProfileResponse(String name, String id) { - this.name = name; - this.id = id; - } - - private final String name; - private final String id; - - public String name() { - return name; - } - - public String id() { - return id; - } -} +public record ProfileResponse(String name, String id) {} diff --git a/src/main/java/pw/kaboom/extras/util/Utility.java b/src/main/java/pw/kaboom/extras/util/Utility.java new file mode 100644 index 0000000..e10c9bb --- /dev/null +++ b/src/main/java/pw/kaboom/extras/util/Utility.java @@ -0,0 +1,16 @@ +package pw.kaboom.extras.util; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import javax.annotation.Nullable; + +public final class Utility { + public static @Nullable Player getPlayerExactIgnoreCase(final String username) { + return Bukkit.getOnlinePlayers() + .stream() + .filter(p -> p.getName().equalsIgnoreCase(username)) + .findFirst() + .orElse(null); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 46a382b..4032abf 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -32,9 +32,13 @@ commands: description: Adds every enchantment to a held item permission: extras.enchantall getjson: - aliases: [ gj, gmm ] - description: Gets the JSON of a deserialized MiniMessage/legacy component + aliases: [ gj ] + description: Gets the JSON of a deserialized legacy component permission: extras.getjson + getjsonmm: + aliases: [ gmm ] + description: Gets the JSON of a deserialized MiniMessage component + permission: extras.getjsonmm jumpscare: aliases: scare description: Scares a player