From e3350acab63c0053ab517add0eba3be0a79c1322 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 27 Dec 2025 11:04:54 +0200 Subject: [PATCH 1/8] Enable using days in ban duration --- src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java b/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java index 5f5cb83..e6a2b18 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java @@ -33,7 +33,7 @@ public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNul final @Nullable String durationArg = args.length > 1 ? args[1] : null; @Nullable Duration duration = null; - if (durationArg != null && durationArg.matches("(?i)^PT\\d.*")) try { + if (durationArg != null && durationArg.matches("(?i)^PT?\\d.*")) try { duration = Duration.parse(durationArg); } catch (DateTimeParseException ignored) { From 3805238dac1a8dd83e61e3d8b17697b227db7ce1 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 27 Dec 2025 12:14:26 +0200 Subject: [PATCH 2/8] Created method for banning without command --- .../smp/smpcore/command/BanCommand.java | 94 ++++++++++++++----- 1 file changed, 71 insertions(+), 23 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java b/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java index e6a2b18..1ba8508 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java @@ -3,7 +3,6 @@ import org.bukkit.NamespacedKey; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.smpcore.Member; @@ -13,6 +12,7 @@ import java.time.Duration; import java.time.Instant; import java.time.format.DateTimeParseException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashSet; @@ -21,6 +21,61 @@ import java.util.Optional; public final class BanCommand extends Command { + private static void ban( + final @NotNull OfflinePlayer player, + final @Nullable String reason, + final @Nullable Date expiry, + final @Nullable String source + ) { + SMPCore.runMain(() -> player.ban(reason, expiry, source)); + } + + /** + * Bans a player and all their alts. + * + * @return List of all banned members, with the main account as the first element. + * + */ + public static @NotNull List<@NotNull Member> ban( + final @NotNull OfflinePlayer player, + final @Nullable String reason, + final @Nullable Duration duration, + final @Nullable OfflinePlayer source + ) { + final String banSource = new NamespacedKey( + SMPCore.getInstance(), + source == null ? "console" : "player/" + source.getUniqueId() + ).asString(); + + final @Nullable Date banExpiry = duration == null + ? null + : Date.from(Instant.now().plus(duration)); + + final Optional targetMember = Member.get(player); + if (targetMember.isEmpty()) { + ban(player, reason, banExpiry, banSource); + return List.of(); + } + + final Member main = targetMember.get().altOwner().orElse(targetMember.get()); + final HashSet alts = main.getAlts(); + + ban(main.player(), reason, banExpiry, banSource); + final List bannedMembers = new ArrayList<>(); + bannedMembers.add(main); + if (alts.isEmpty()) return bannedMembers; + + for (final Member alt : alts) { + ban(alt.player(), reason, banExpiry, banSource); + bannedMembers.add(alt); + } + return bannedMembers; + } + /** * Usage: {@code / [duration] [reason]} */ @@ -43,34 +98,27 @@ public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNul if (duration != null && (duration.isNegative() || duration.isZero())) return sendMessage(sender, SMPCore.messages().errorDurationZeroOrLess()); - final @Nullable Date banExpiry = duration == null ? null : Date.from(Instant.now().plus(duration)); - final @Nullable String reason = args.length > 1 ? String.join(" ", Arrays.copyOfRange(args, duration == null ? 1 : 2, args.length)) : null; - final @NotNull NamespacedKey banSource; - if (sender instanceof final @NotNull Player player) - banSource = new NamespacedKey(SMPCore.getInstance(), "player/" + player.getUniqueId()); - else banSource = new NamespacedKey(SMPCore.getInstance(), "console"); final @NotNull OfflinePlayer target = SMPCore.getInstance().getServer().getOfflinePlayer(args[0]); - final @NotNull Optional<@NotNull Member> targetMember = Member.get(target); - if (targetMember.isEmpty()) { - SMPCore.runMain(() -> target.ban(reason, banExpiry, banSource.asString())); + + final List banned = ban( + target, + reason, + duration, + sender instanceof final OfflinePlayer player ? player : null + ); + + if (banned.isEmpty()) return sendMessage(sender, SMPCore.messages().bannedPlayer(target, duration)); - } - final @NotNull Member main = targetMember.get().altOwner().orElse(targetMember.get()); - final @NotNull HashSet<@NotNull Member> alts = main.getAlts(); - - SMPCore.runMain(() -> main.player().ban(reason, banExpiry, banSource.asString())); - if (alts.isEmpty()) return sendMessage(sender, SMPCore.messages().bannedMember(main, duration)); - else { - SMPCore.runMain(() -> { - for (final @NotNull Member alt : alts) - alt.player().ban(reason, banExpiry, banSource.asString()); - }); - return sendMessage(sender, SMPCore.messages().bannedMemberChain(main, alts.stream().toList(), duration)); - } + if (banned.size() == 1) + return sendMessage(sender, SMPCore.messages().bannedMember(banned.get(0), duration)); + return sendMessage(sender, SMPCore.messages().bannedMemberChain( + banned.get(0), + banned.subList(1, banned.size()), duration) + ); } @Override From a94ab8bb3ca0f2aecdb82d868fa4b125f3dc104d Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 27 Dec 2025 21:45:31 +0200 Subject: [PATCH 3/8] ban on death --- .../cloudnode/smp/smpcore/Configuration.java | 20 +++++++++ .../pro/cloudnode/smp/smpcore/Permission.java | 5 +++ .../pro/cloudnode/smp/smpcore/SMPCore.java | 2 + .../smpcore/listener/PlayerDeathListener.java | 42 +++++++++++++++++++ src/main/resources/config.yml | 22 ++++++++++ 5 files changed, 91 insertions(+) create mode 100644 src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Configuration.java b/src/main/java/pro/cloudnode/smp/smpcore/Configuration.java index 87f3d2e..9c6f0d3 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Configuration.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Configuration.java @@ -6,7 +6,9 @@ import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.jetbrains.annotations.NotNull; +import java.time.Duration; import java.time.temporal.ChronoUnit; +import java.util.List; import java.util.Objects; public final class Configuration extends BaseConfig { @@ -42,6 +44,24 @@ public int joinRequestExpireMinutes() { return config.getInt("join.request-expire-minutes"); } + /** + * Ban players upon death + */ + public boolean deathBanEnabled() { + return config.getBoolean("death-ban.enabled"); + } + + public @NotNull Component deathBanMessage() { + return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("death-ban.message"))); + } + + public @NotNull Duration deathBanProgression(final int index) { + List progression = config.getStringList("death-ban.progression") + .stream().map(Duration::parse).toList(); + if (index >= progression.size()) progression.getLast(); + return progression.get(index); + } + public @NotNull Component relativeTime(final Number t, final @NotNull ChronoUnit unit) { final @NotNull String formatString = Objects.requireNonNull(config.getString("relative-time." + switch (unit) { case SECONDS -> "seconds"; diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Permission.java b/src/main/java/pro/cloudnode/smp/smpcore/Permission.java index 40bc930..2433bb1 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Permission.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Permission.java @@ -156,4 +156,9 @@ public final class Permission { * Relieve vice-leader of any nation of their duties */ public static @NotNull String NATION_DEMOTE_OTHER = "smpcore.nation.citizens.demote.other"; + + /** + * Bypass death ban. + */ + public static @NotNull String DEATHBAN_BYPASS = "smpcore.deathban.bypass"; } diff --git a/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java b/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java index 57ad51c..5d050b1 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java @@ -17,6 +17,7 @@ import pro.cloudnode.smp.smpcore.command.TimeCommand; import pro.cloudnode.smp.smpcore.command.UnbanCommand; import pro.cloudnode.smp.smpcore.listener.NationTeamUpdaterListener; +import pro.cloudnode.smp.smpcore.listener.PlayerDeathListener; import pro.cloudnode.smp.smpcore.listener.PlayerSlotsListener; import java.io.IOException; @@ -73,6 +74,7 @@ public void onEnable() { getServer().getPluginManager().registerEvents(new NationTeamUpdaterListener(), this); getServer().getPluginManager().registerEvents(new PlayerSlotsListener(), this); + getServer().getPluginManager().registerEvents(new PlayerDeathListener(), this); final @NotNull HashMap<@NotNull String, @NotNull Command> commands = new HashMap<>() {{ put("smpcore", new MainCommand()); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java new file mode 100644 index 0000000..7e5dde6 --- /dev/null +++ b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java @@ -0,0 +1,42 @@ +package pro.cloudnode.smp.smpcore.listener; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.bukkit.Statistic; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.jetbrains.annotations.NotNull; +import pro.cloudnode.smp.smpcore.Permission; +import pro.cloudnode.smp.smpcore.SMPCore; +import pro.cloudnode.smp.smpcore.command.BanCommand; + +import java.util.Optional; + +public final class PlayerDeathListener implements Listener { + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void banPlayer(final @NotNull PlayerDeathEvent event) { + if (!SMPCore.config().deathBanEnabled()) + return; + + final @NotNull Player player = event.getPlayer(); + + if (player.hasPermission(Permission.DEATHBAN_BYPASS)) + return; + + player.spigot().respawn(); + player.setGameMode(SMPCore.getInstance().getServer().getDefaultGameMode()); + + final Component reason = Optional.ofNullable(event.deathMessage()) + .orElse(SMPCore.config().deathBanMessage()); + + BanCommand.ban( + player, + PlainTextComponentSerializer.plainText().serialize(reason), + SMPCore.config().deathBanProgression(player.getStatistic(Statistic.DEATHS)), + null + ); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ce6decf..ee1baa8 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -14,6 +14,28 @@ join: # The number of minutes after which requests/invitations to join a nation expire request-expire-minutes: 1440 +# Ban players upon death +death-ban: + enabled: true + message: + + # Ban durations + progression: + - PT1M + - PT2M + - PT5M + - PT10M + - PT20M + - PT45M + - PT1H30M + - PT3H + - PT6H + - PT12H + - P1D + - P3D + - P7D + - P14D + relative-time: seconds: minutes: From 3a2bc67c49195d27e58a30305a3cfd316f7c975e Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 27 Dec 2025 21:46:13 +0200 Subject: [PATCH 4/8] customise ban screen --- .../pro/cloudnode/smp/smpcore/Messages.java | 21 ++++++++++++++ .../pro/cloudnode/smp/smpcore/SMPCore.java | 2 ++ .../listener/PlayerPreLoginListener.java | 29 +++++++++++++++++++ src/main/resources/messages.yml | 13 +++++++++ 4 files changed, 65 insertions(+) create mode 100644 src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerPreLoginListener.java diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Messages.java b/src/main/java/pro/cloudnode/smp/smpcore/Messages.java index 57bc1a9..1b29b95 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Messages.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Messages.java @@ -1,11 +1,14 @@ package pro.cloudnode.smp.smpcore; +import com.destroystokyo.paper.profile.PlayerProfile; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Formatter; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import org.bukkit.BanEntry; import org.bukkit.OfflinePlayer; import org.bukkit.permissions.Permissible; import org.jetbrains.annotations.NotNull; @@ -13,6 +16,7 @@ import java.time.Duration; import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; @@ -463,6 +467,23 @@ public Messages() { ); } + public @NotNull Optional<@NotNull Component> banScreen(final @NotNull BanEntry banEntry) { + final @Nullable Date expiration = banEntry.getExpiration(); + final @Nullable String template = config.getString("ban-screen." + (expiration == null ? "permanent" : "temporary")); + if (template == null || template.isBlank() || template.equals("null")) + return Optional.empty(); + + List placeholders = new ArrayList<>(); + placeholders.add(Placeholder.unparsed("reason", Optional.ofNullable(banEntry.getReason()).orElse(""))); + if (expiration != null) { + final @NotNull ZonedDateTime localExpiry = expiration.toInstant().atZone(ZoneOffset.systemDefault()); + placeholders.add(Formatter.date("expiration", localExpiry)); + placeholders.add(Placeholder.component("expiration-relative", SMPCore.relativeTime(expiration))); + } + + return Optional.of(MiniMessage.miniMessage().deserialize(template, placeholders.toArray(TagResolver[]::new))); + } + // errors public @NotNull Component errorNoPermission() { diff --git a/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java b/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java index 5d050b1..15e8375 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java @@ -19,6 +19,7 @@ import pro.cloudnode.smp.smpcore.listener.NationTeamUpdaterListener; import pro.cloudnode.smp.smpcore.listener.PlayerDeathListener; import pro.cloudnode.smp.smpcore.listener.PlayerSlotsListener; +import pro.cloudnode.smp.smpcore.listener.PlayerPreLoginListener; import java.io.IOException; import java.io.InputStream; @@ -75,6 +76,7 @@ public void onEnable() { getServer().getPluginManager().registerEvents(new NationTeamUpdaterListener(), this); getServer().getPluginManager().registerEvents(new PlayerSlotsListener(), this); getServer().getPluginManager().registerEvents(new PlayerDeathListener(), this); + getServer().getPluginManager().registerEvents(new PlayerPreLoginListener(), this); final @NotNull HashMap<@NotNull String, @NotNull Command> commands = new HashMap<>() {{ put("smpcore", new MainCommand()); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerPreLoginListener.java b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerPreLoginListener.java new file mode 100644 index 0000000..fd118c2 --- /dev/null +++ b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerPreLoginListener.java @@ -0,0 +1,29 @@ +package pro.cloudnode.smp.smpcore.listener; + +import com.destroystokyo.paper.profile.PlayerProfile; +import io.papermc.paper.ban.BanListType; +import org.bukkit.BanEntry; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import pro.cloudnode.smp.smpcore.SMPCore; + +public final class PlayerPreLoginListener implements Listener { + @EventHandler(priority = EventPriority.HIGHEST) + public void formatBanScreen(final @NotNull AsyncPlayerPreLoginEvent event) { + if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) + return; + + @Nullable BanEntry banEntry = SMPCore.getInstance().getServer() + .getBanList(BanListType.PROFILE).getBanEntry(event.getPlayerProfile()); + + if (banEntry == null) + return; + + SMPCore.messages().banScreen(banEntry) + .ifPresent(reason -> event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, reason)); + } +} diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index ec047f3..acccd8c 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -83,6 +83,19 @@ nation: request-rejected: (!) You have rejected the request of to join . invite-cancelled: (!) You have cancelled the invitation to to join . invite-rejected: (!) You have rejected the invitation to join . + +ban-screen: + permanent: |- + + + + + temporary: |- + + + + at '> (). + error: no-permission: (!) You don't have permission to use this command. player-not-banned: (!) Player is not banned and is not a member. From a6aa76ee0dc4f05fa70d59b15757ccb3076fd628 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 27 Dec 2025 22:05:42 +0200 Subject: [PATCH 5/8] simplify getting server --- .../pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java index 7e5dde6..dd394ef 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerDeathListener.java @@ -27,7 +27,7 @@ public void banPlayer(final @NotNull PlayerDeathEvent event) { return; player.spigot().respawn(); - player.setGameMode(SMPCore.getInstance().getServer().getDefaultGameMode()); + player.setGameMode(player.getServer().getDefaultGameMode()); final Component reason = Optional.ofNullable(event.deathMessage()) .orElse(SMPCore.config().deathBanMessage()); From dd5b426763bc32697eb0d8dcca065e620efabf39 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 27 Dec 2025 22:06:57 +0200 Subject: [PATCH 6/8] enforce default gamemode on respawn unless have perms for `/gamemode` --- .../pro/cloudnode/smp/smpcore/SMPCore.java | 2 ++ .../listener/PlayerPostRespawnListener.java | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerPostRespawnListener.java diff --git a/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java b/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java index 15e8375..ee5b0a6 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java @@ -18,6 +18,7 @@ import pro.cloudnode.smp.smpcore.command.UnbanCommand; import pro.cloudnode.smp.smpcore.listener.NationTeamUpdaterListener; import pro.cloudnode.smp.smpcore.listener.PlayerDeathListener; +import pro.cloudnode.smp.smpcore.listener.PlayerPostRespawnListener; import pro.cloudnode.smp.smpcore.listener.PlayerSlotsListener; import pro.cloudnode.smp.smpcore.listener.PlayerPreLoginListener; @@ -77,6 +78,7 @@ public void onEnable() { getServer().getPluginManager().registerEvents(new PlayerSlotsListener(), this); getServer().getPluginManager().registerEvents(new PlayerDeathListener(), this); getServer().getPluginManager().registerEvents(new PlayerPreLoginListener(), this); + getServer().getPluginManager().registerEvents(new PlayerPostRespawnListener(), this); final @NotNull HashMap<@NotNull String, @NotNull Command> commands = new HashMap<>() {{ put("smpcore", new MainCommand()); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerPostRespawnListener.java b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerPostRespawnListener.java new file mode 100644 index 0000000..c25be91 --- /dev/null +++ b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerPostRespawnListener.java @@ -0,0 +1,20 @@ +package pro.cloudnode.smp.smpcore.listener; + +import com.destroystokyo.paper.event.player.PlayerPostRespawnEvent; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; + +public final class PlayerPostRespawnListener implements Listener { + @EventHandler(priority = EventPriority.HIGHEST) + public void enforceDefaultGamemode(final @NotNull PlayerPostRespawnEvent event) { + final Player player = event.getPlayer(); + + if (player.hasPermission("minecraft.command.gamemode")) + return; + + player.setGameMode(player.getServer().getDefaultGameMode()); + } +} From 12617491225181fe81bbea485526395ae4bba4d9 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 27 Dec 2025 22:10:48 +0200 Subject: [PATCH 7/8] fix typo --- src/main/resources/messages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index acccd8c..ab67ef8 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -94,7 +94,7 @@ ban-screen: - at '> (). + at '> (). error: no-permission: (!) You don't have permission to use this command. From 488e6fce11255ca924737d9b989862b6afa3734c Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sun, 28 Dec 2025 11:00:04 +0200 Subject: [PATCH 8/8] code style fixes --- src/main/java/pro/cloudnode/smp/smpcore/Permission.java | 2 +- .../java/pro/cloudnode/smp/smpcore/command/BanCommand.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Permission.java b/src/main/java/pro/cloudnode/smp/smpcore/Permission.java index 2433bb1..36c57ab 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Permission.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Permission.java @@ -160,5 +160,5 @@ public final class Permission { /** * Bypass death ban. */ - public static @NotNull String DEATHBAN_BYPASS = "smpcore.deathban.bypass"; + public static final @NotNull String DEATHBAN_BYPASS = "smpcore.deathban.bypass"; } diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java b/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java index 1ba8508..d352ee7 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java @@ -15,10 +15,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; public final class BanCommand extends Command { private static void ban( @@ -62,7 +62,7 @@ private static void ban( } final Member main = targetMember.get().altOwner().orElse(targetMember.get()); - final HashSet alts = main.getAlts(); + final Set alts = main.getAlts(); ban(main.player(), reason, banExpiry, banSource); final List bannedMembers = new ArrayList<>();