Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions api/src/main/java/dev/plex/api/command/CommandApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import dev.plex.command.PlexCommand;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import net.kyori.adventure.text.Component;

/**
* Registers and unregisters Plex commands with the running platform.
Expand Down Expand Up @@ -47,4 +50,16 @@ public interface CommandApi
* after the active command lifecycle was built
*/
boolean requiresLifecycleReload();

/**
* Dispatches a console-capable command with a human-readable audit identity.
* The command must be invoked from the server's global command thread.
*
* @param identityId UUID exposed as the command actor
* @param identityName name exposed by Plex command contexts
* @param command command line without a leading slash
* @param feedback receiver for command feedback
* @return whether the command was accepted by the dispatcher
*/
boolean dispatchAsConsole(UUID identityId, String identityName, String command, Consumer<? super Component> feedback);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package dev.plex.api.command;

import java.util.UUID;
import java.util.function.Supplier;
import org.jetbrains.annotations.ApiStatus;

/** Carries an attributed command name through a synchronous Plex command dispatch. */
@ApiStatus.Internal
public final class CommandExecutionIdentity
{
private static final ThreadLocal<Identity> IDENTITY = new ThreadLocal<>();

private CommandExecutionIdentity()
{
}

public static <T> T call(UUID uniqueId, String name, Supplier<T> action)
{
Identity previous = IDENTITY.get();
IDENTITY.set(new Identity(uniqueId, name));
try
{
return action.get();
}
finally
{
if (previous == null)
{
IDENTITY.remove();
}
else
{
IDENTITY.set(previous);
}
}
}

public static String currentName(String fallback)
{
Identity identity = IDENTITY.get();
return identity == null || identity.name() == null || identity.name().isBlank() ? fallback : identity.name();
}

public static UUID currentUniqueId()
{
Identity identity = IDENTITY.get();
return identity == null ? null : identity.uniqueId();
}

private record Identity(UUID uniqueId, String name) { }
}
14 changes: 14 additions & 0 deletions server/src/main/java/dev/plex/api/impl/DefaultCommandApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

import dev.plex.Plex;
import dev.plex.api.command.CommandApi;
import dev.plex.api.command.CommandExecutionIdentity;
import dev.plex.command.PlexCommand;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;

final class DefaultCommandApi implements CommandApi
{
Expand Down Expand Up @@ -47,4 +52,13 @@ public boolean requiresLifecycleReload()
{
return plugin.getCommandHandler() != null && plugin.getCommandHandler().requiresLifecycleReload();
}

@Override
public boolean dispatchAsConsole(UUID identityId, String identityName, String command, Consumer<? super Component> feedback)
{
return CommandExecutionIdentity.call(
identityId,
identityName,
() -> Bukkit.dispatchCommand(Bukkit.createCommandSender(feedback), command));
}
}
4 changes: 2 additions & 2 deletions server/src/main/java/dev/plex/command/ServerCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ private boolean canUse(CommandSourceStack source)
return false;
}

if (commandSource == RequiredCommandSource.IN_GAME && sender instanceof ConsoleCommandSender)
if (commandSource == RequiredCommandSource.IN_GAME && !(sender instanceof Player))
{
return false;
}
Expand Down Expand Up @@ -319,7 +319,7 @@ private boolean validateSourceAndPermission(CommandSender sender, ServerCommandC
return false;
}

if (commandSource == RequiredCommandSource.IN_GAME && sender instanceof ConsoleCommandSender)
if (commandSource == RequiredCommandSource.IN_GAME && context.isConsole())
{
context.send(sender, context.messageComponent("noPermissionConsole"));
return false;
Expand Down
35 changes: 31 additions & 4 deletions server/src/main/java/dev/plex/command/ServerCommandContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.mojang.brigadier.context.CommandContext;
import dev.plex.Plex;
import dev.plex.api.command.CommandExecutionIdentity;
import dev.plex.command.exception.CommandFailException;
import dev.plex.command.exception.ConsoleMustDefinePlayerException;
import dev.plex.command.exception.ConsoleOnlyException;
Expand Down Expand Up @@ -32,6 +33,8 @@ public final class ServerCommandContext
private final PlexCommand command;
private final CommandContext<CommandSourceStack> brigadierContext;
private final CommandSender sender;
private final String senderName;
private final UUID senderUuid;
private final Player player;
private final String[] args;

Expand All @@ -41,6 +44,10 @@ public final class ServerCommandContext
this.command = command;
this.brigadierContext = brigadierContext;
this.sender = brigadierContext.getSource().getSender();
this.senderName = CommandExecutionIdentity.currentName(sender.getName());
this.senderUuid = sender instanceof Player playerSender
? playerSender.getUniqueId()
: CommandExecutionIdentity.currentUniqueId();
this.player = sender instanceof Player playerSender ? playerSender : null;
this.args = args;
}
Expand Down Expand Up @@ -85,6 +92,26 @@ public CommandSender sender()
return sender;
}

/**
* Returns the attributed sender name for messages and audit logs.
*
* @return attributed sender name
*/
public String senderName()
{
return senderName;
}

/**
* Returns the attributed sender UUID, if available.
*
* @return attributed sender UUID, or {@code null}
*/
public @Nullable UUID senderUuid()
{
return senderUuid;
}

/**
* Returns the player sender, if this command was run by a player.
*
Expand Down Expand Up @@ -131,7 +158,7 @@ public boolean checkPermission(CommandSender sender, String permission)

public boolean silentCheckPermission(CommandSender sender, String permission)
{
PlexLog.debug("Checking {0} with {1}", sender.getName(), permission);
PlexLog.debug("Checking {0} with {1}", senderName, permission);
if (!isConsole(sender))
{
return silentCheckPermission((Player)sender, permission);
Expand All @@ -155,11 +182,11 @@ public boolean silentCheckPermission(Player player, String permission)

public @Nullable UUID getUUID(CommandSender sender)
{
if (!(sender instanceof Player player))
if (sender instanceof Player player)
{
return null;
return player.getUniqueId();
}
return player.getUniqueId();
return sender == this.sender ? senderUuid : null;
}

public boolean isConsole(CommandSender sender)
Expand Down
4 changes: 2 additions & 2 deletions server/src/main/java/dev/plex/command/impl/AdminChatCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ protected Component execute(@NotNull ServerCommandContext context)
}
Component eventMessage = staffChatEvent.getMessage();
String serializedMessage = SafeMiniMessage.mmSerialize(eventMessage);
plugin.getServer().getConsoleSender().sendMessage(context.messageComponent("adminChatFormat", sender.getName(), prefix, serializedMessage));
MessageUtil.sendStaffChat(plugin, sender, eventMessage, PlexUtils.adminChat(sender.getName(), prefix, serializedMessage).toArray(UUID[]::new));
plugin.getServer().getConsoleSender().sendMessage(context.messageComponent("adminChatFormat", context.senderName(), prefix, serializedMessage));
MessageUtil.sendStaffChat(plugin, sender, eventMessage, PlexUtils.adminChat(context.senderName(), prefix, serializedMessage).toArray(UUID[]::new));
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ protected Component execute(@NotNull ServerCommandContext context)
targetPlayer.setGameMode(GameMode.ADVENTURE);
context.messageComponent("gameModeSetTo", "adventure");
}
PlexUtils.broadcast(context.messageComponent("setEveryoneGameMode", sender.getName(), "adventure"));
PlexUtils.broadcast(context.messageComponent("setEveryoneGameMode", context.senderName(), "adventure"));
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/dev/plex/command/impl/BanCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ protected Component execute(@NotNull ServerCommandContext context)
punishment.setActive(true);
punishment.setIp(plexPlayer.getIps().getLast());
plugin.getPunishmentManager().punish(plexPlayer, punishment);
PlexUtils.broadcast(context.messageComponent("banningPlayer", sender.getName(), plexPlayer.getName()));
PlexUtils.broadcast(context.messageComponent("banningPlayer", context.senderName(), plexPlayer.getName()));
if (player != null)
{
plugin.getApi().scheduler().runEntity(player, () -> BungeeUtil.kickPlayer(plugin, player, Punishment.generateBanMessage(punishment, plugin.config.getString("banning.ban_url"), plugin.getPlayerNameResolver())));
Expand Down
8 changes: 4 additions & 4 deletions server/src/main/java/dev/plex/command/impl/BlockEditCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected Component execute(@NotNull ServerCommandContext context)
}
else if (args[0].equalsIgnoreCase("purge"))
{
PlexUtils.broadcast(context.messageComponent("unblockingEdits", sender.getName(), context.messageString("blockeditAllPlayers")));
PlexUtils.broadcast(context.messageComponent("unblockingEdits", context.senderName(), context.messageString("blockeditAllPlayers")));
int count = 0;
for (String player : BlockListener.blockedPlayers.stream().toList())
{
Expand All @@ -84,7 +84,7 @@ else if (args[0].equalsIgnoreCase("purge"))
}
else if (args[0].equalsIgnoreCase("all"))
{
PlexUtils.broadcast(context.messageComponent("blockingEdits", sender.getName(), context.messageString("blockeditAllNonAdmins")));
PlexUtils.broadcast(context.messageComponent("blockingEdits", context.senderName(), context.messageString("blockeditAllNonAdmins")));
int count = 0;
for (final Player player : Bukkit.getOnlinePlayers())
{
Expand All @@ -106,14 +106,14 @@ else if (args[0].equalsIgnoreCase("all"))
context.send(sender, context.messageComponent("higherRankThanYou"));
return null;
}
PlexUtils.broadcast(context.messageComponent("blockingEdits", sender.getName(), player.getName()));
PlexUtils.broadcast(context.messageComponent("blockingEdits", context.senderName(), player.getName()));
BlockListener.blockedPlayers.add(player.getName());
context.send(player, context.messageComponent("editsModified", context.messageString("blockeditBlockedState")));
context.send(sender, context.messageComponent("editsBlocked", player.getName()));
}
else
{
PlexUtils.broadcast(context.messageComponent("unblockingEdits", sender.getName(), player.getName()));
PlexUtils.broadcast(context.messageComponent("unblockingEdits", context.senderName(), player.getName()));
BlockListener.blockedPlayers.remove(player.getName());
context.send(player, context.messageComponent("editsModified", context.messageString("blockeditUnblockedState")));
context.send(sender, context.messageComponent("editsUnblocked", player.getName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ protected Component execute(@NotNull ServerCommandContext context)
return context.usage();
}

PlexUtils.broadcast(PlexUtils.messageComponent("consoleSayMessage", sender.getName(), PlexUtils.mmStripColor(StringUtils.join(args, " "))));
PlexUtils.broadcast(PlexUtils.messageComponent("consoleSayMessage", context.senderName(), PlexUtils.mmStripColor(StringUtils.join(args, " "))));
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ protected Component execute(@NotNull ServerCommandContext context)
targetPlayer.setGameMode(GameMode.CREATIVE);
context.messageComponent("gameModeSetTo", "creative");
}
PlexUtils.broadcast(context.messageComponent("setEveryoneGameMode", sender.getName(), "creative"));
PlexUtils.broadcast(context.messageComponent("setEveryoneGameMode", context.senderName(), "creative"));
return null;
}

Expand Down
4 changes: 2 additions & 2 deletions server/src/main/java/dev/plex/command/impl/EntityWipeCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ protected Component execute(@NotNull ServerCommandContext context)

if (useBlacklist)
{
PlexUtils.broadcast(context.messageComponent("removedEntities", sender.getName(), entityCount));
PlexUtils.broadcast(context.messageComponent("removedEntities", context.senderName(), entityCount));
}
else
{
Expand All @@ -138,7 +138,7 @@ protected Component execute(@NotNull ServerCommandContext context)
}
String list = String.join(", ", entityCounts.keySet());
list = list.replaceAll("(, )(?!.*\1)", (list.indexOf(", ") == list.lastIndexOf(", ") ? "" : ",") + " and ");
PlexUtils.broadcast(context.messageComponent("removedEntitiesOfTypes", sender.getName(), entityCount, list));
PlexUtils.broadcast(context.messageComponent("removedEntitiesOfTypes", context.senderName(), entityCount, list));
}
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/dev/plex/command/impl/FreezeCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected Component execute(@NotNull ServerCommandContext context)
punishment.setActive(true);

plugin.getPunishmentManager().punish(punishedPlayer, punishment);
PlexUtils.broadcast(context.messageComponent("frozePlayer", sender.getName(), player.getName()));
PlexUtils.broadcast(context.messageComponent("frozePlayer", context.senderName(), player.getName()));
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/dev/plex/command/impl/KickCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected Component execute(@NotNull ServerCommandContext context)
punishment.setActive(false);
punishment.setIp(player.getAddress().getAddress().getHostAddress().trim());
plugin.getPunishmentManager().punish(plexPlayer, punishment);
PlexUtils.broadcast(context.messageComponent("kickedPlayer", sender.getName(), plexPlayer.getName()));
PlexUtils.broadcast(context.messageComponent("kickedPlayer", context.senderName(), plexPlayer.getName()));
BungeeUtil.kickPlayer(plugin, player, Punishment.generateKickMessage(punishment, plugin.getPlayerNameResolver()));
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/dev/plex/command/impl/LockupCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected Component execute(@NotNull ServerCommandContext context)
{
player.openInventory(player.getInventory());
}
PlexUtils.broadcast(context.messageComponent(punishedPlayer.isLockedUp() ? "lockedUpPlayer" : "unlockedPlayer", sender.getName(), player.getName()));
PlexUtils.broadcast(context.messageComponent(punishedPlayer.isLockedUp() ? "lockedUpPlayer" : "unlockedPlayer", context.senderName(), player.getName()));
return null;
}

Expand Down
4 changes: 2 additions & 2 deletions server/src/main/java/dev/plex/command/impl/MobPurgeCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ protected Component execute(@NotNull ServerCommandContext context)
int count = purgeMobs(type);
if (type != null)
{
PlexUtils.broadcast(context.messageComponent("removedEntitiesOfTypes", sender.getName(), count, mobName));
PlexUtils.broadcast(context.messageComponent("removedEntitiesOfTypes", context.senderName(), count, mobName));
PlexLog.debug("All " + count + " of " + mobName + " were removed");
}
else
{
PlexUtils.broadcast(context.messageComponent("removedMobs", sender.getName(), count));
PlexUtils.broadcast(context.messageComponent("removedMobs", context.senderName(), count));
PlexLog.debug("All " + count + " valid mobs were removed");
}
sender.sendMessage(context.messageComponent("amountOfMobsRemoved", count, type != null ? mobName + multipleS(count) : context.messageString(count == 1 ? "mobSingular" : "mobPlural")));
Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/dev/plex/command/impl/MuteCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ protected Component execute(@NotNull ServerCommandContext context)
punishment.setActive(true);

plugin.getPunishmentManager().punish(punishedPlayer, punishment);
PlexUtils.broadcast(context.messageComponent("mutedPlayer", sender.getName(), player.getName()));
PlexUtils.broadcast(context.messageComponent("mutedPlayer", context.senderName(), player.getName()));
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/dev/plex/command/impl/SayCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected Component execute(@NotNull ServerCommandContext context)
return context.usage();
}

PlexUtils.broadcast(PlexUtils.messageComponent("sayMessage", sender.getName(), PlexUtils.mmStripColor(StringUtils.join(args, " "))));
PlexUtils.broadcast(PlexUtils.messageComponent("sayMessage", context.senderName(), PlexUtils.mmStripColor(StringUtils.join(args, " "))));
return null;
}

Expand Down
4 changes: 2 additions & 2 deletions server/src/main/java/dev/plex/command/impl/SmiteCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ protected Component execute(@NotNull ServerCommandContext context)
final Player player = context.getNonNullPlayer(args[0]);
final PlexPlayer plexPlayer = context.getPlexPlayer(player);

Title title = Title.title(context.messageComponent("smiteTitleHeader"), context.messageComponent("smiteTitleMessage", reason, sender.getName()));
Title title = Title.title(context.messageComponent("smiteTitleHeader"), context.messageComponent("smiteTitleMessage", reason, context.senderName()));
player.showTitle(title);

if (!silent)
{
PlexUtils.broadcast(context.messageComponent("smiteBroadcast", player.getName(), reason != null ? reason : context.messageString("noReasonProvided"), sender.getName()));
PlexUtils.broadcast(context.messageComponent("smiteBroadcast", player.getName(), reason != null ? reason : context.messageString("noReasonProvided"), context.senderName()));
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ protected Component execute(@NotNull ServerCommandContext context)
targetPlayer.setGameMode(GameMode.SPECTATOR);
context.messageComponent("gameModeSetTo", "spectator");
}
PlexUtils.broadcast(context.messageComponent("setEveryoneGameMode", sender.getName(), "spectator"));
PlexUtils.broadcast(context.messageComponent("setEveryoneGameMode", context.senderName(), "spectator"));
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ protected Component execute(@NotNull ServerCommandContext context)
targetPlayer.setGameMode(GameMode.SURVIVAL);
context.send(targetPlayer, context.messageComponent("gameModeSetTo", "survival"));
}
PlexUtils.broadcast(context.messageComponent("setEveryoneGameMode", sender.getName(), "survival"));
PlexUtils.broadcast(context.messageComponent("setEveryoneGameMode", context.senderName(), "survival"));
return null;
}

Expand Down
Loading
Loading