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 extends Player> 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