Skip to content

Commit

Permalink
Fix permissions not working for subcommands (#158)
Browse files Browse the repository at this point in the history
Signed-off-by: Lyfts <127234178+Lyfts@users.noreply.github.com>
Co-authored-by: Maya <10861407+serenibyss@users.noreply.github.com>
  • Loading branch information
Lyfts and serenibyss authored Dec 15, 2024
1 parent 815a843 commit e820429
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 19 deletions.
20 changes: 15 additions & 5 deletions src/main/java/serverutils/lib/command/CommandTreeBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.ChatComponentTranslation;

import serverutils.ranks.ICommandWithPermission;

/**
* Base class for commands that has subcommands.
* <p>
Expand Down Expand Up @@ -108,14 +110,14 @@ public boolean isUsernameIndex(String[] args, int index) {
@Override
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
if (args.length < 1) {
String subCommandsString = getAvailableSubCommandsString(MinecraftServer.getServer(), sender);
String subCommandsString = getAvailableSubCommandsString(sender);
sender.addChatMessage(
new ChatComponentTranslation("commands.tree_base.available_subcommands", subCommandsString));
} else {
ICommand cmd = getSubCommand(args[0]);

if (cmd == null) {
String subCommandsString = getAvailableSubCommandsString(MinecraftServer.getServer(), sender);
String subCommandsString = getAvailableSubCommandsString(sender);
throw new CommandException(
"commands.tree_base.invalid_cmd.list_subcommands",
args[0],
Expand All @@ -128,13 +130,21 @@ public void processCommand(ICommandSender sender, String[] args) throws CommandE
}
}

private String getAvailableSubCommandsString(MinecraftServer server, ICommandSender sender) {
private String getAvailableSubCommandsString(ICommandSender sender) {
Collection<String> availableCommands = new ArrayList<>();
for (ICommand command : getSubCommands()) {
if (command.canCommandSenderUseCommand(sender)) {
if (canUseSubcommand(sender, command)) {
availableCommands.add(command.getCommandName());
}
}
return CommandBase.joinNiceStringFromCollection(availableCommands);
}

private boolean canUseSubcommand(ICommandSender sender, ICommand command) {
if (command instanceof ICommandWithPermission permCmd && sender instanceof EntityPlayerMP player) {
return permCmd.serverutilities$hasPermission(player);
}

return command.canCommandSenderUseCommand(sender);
}
}
4 changes: 4 additions & 0 deletions src/main/java/serverutils/ranks/ICommandWithPermission.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.HashMap;
import java.util.Map;

import net.minecraft.entity.player.EntityPlayerMP;

import org.jetbrains.annotations.NotNull;

public interface ICommandWithPermission {
Expand All @@ -18,4 +20,6 @@ public interface ICommandWithPermission {
String serverutilities$getModName();

void serverutilities$setModName(@NotNull String modName);

boolean serverutilities$hasPermission(EntityPlayerMP player);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.eventhandler.Event;
import serverutils.ServerUtilitiesPermissions;
import serverutils.data.NodeEntry;
import serverutils.lib.command.CommandTreeBase;
import serverutils.lib.util.permission.DefaultPermissionLevel;
import serverutils.lib.util.permission.PermissionAPI;
import serverutils.ranks.ICommandWithPermission;
import serverutils.ranks.Rank;
import serverutils.ranks.Ranks;

@Mixin(CommandHandler.class)
public abstract class MixinCommandHandler {
Expand All @@ -38,24 +36,31 @@ public abstract class MixinCommandHandler {
private static final Matcher PERMISSION_REPLACE_MATCHER = Pattern.compile("[^a-zA-Z0-9._]").matcher("");

@ModifyExpressionValue(
method = { "getPossibleCommands(Lnet/minecraft/command/ICommandSender;)Ljava/util/List;",
"executeCommand" },
method = "getPossibleCommands(Lnet/minecraft/command/ICommandSender;)Ljava/util/List;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/command/ICommand;canCommandSenderUseCommand(Lnet/minecraft/command/ICommandSender;)Z"))
private boolean serverutilities$checkPermission(boolean original, @Local(argsOnly = true) ICommandSender sender,
@Local ICommand command) {
if (sender instanceof EntityPlayerMP player) {
Event.Result result = Ranks.INSTANCE.getPermissionResult(
player,
((ICommandWithPermission) command).serverutilities$getPermissionNode(),
true);

if (result != Event.Result.DEFAULT) {
return result == Event.Result.ALLOW;
}
if (!(sender instanceof EntityPlayerMP player)) return original;
return ((ICommandWithPermission) command).serverutilities$hasPermission(player);
}

@ModifyExpressionValue(
method = "executeCommand",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/command/ICommand;canCommandSenderUseCommand(Lnet/minecraft/command/ICommandSender;)Z"))
private boolean serverutilities$checkPermissionExecute(boolean original,
@Local(argsOnly = true) ICommandSender sender, @Local ICommand command, @Local String[] args) {
if (!(sender instanceof EntityPlayerMP player)) return original;

if (command instanceof CommandTreeBase treeCmd && args.length >= 1) {
ICommand subCommand = treeCmd.getSubCommand(args[0]);
if (subCommand != null) command = subCommand;
}
return original;

return ((ICommandWithPermission) command).serverutilities$hasPermission(player);
}

@Inject(method = "registerCommand", at = @At(value = "HEAD"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
package serverutils.mixins.early.minecraft;

import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.player.EntityPlayerMP;

import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;

import cpw.mods.fml.common.eventhandler.Event;
import serverutils.ranks.ICommandWithPermission;
import serverutils.ranks.Ranks;

@Mixin(ICommand.class)
public interface MixinICommand extends ICommandWithPermission {

@Shadow
String getCommandName();

@Shadow
boolean canCommandSenderUseCommand(ICommandSender sender);

@Override
default String serverutilities$getPermissionNode() {
return commandPermissions.get(getCommandName());
Expand All @@ -33,4 +40,14 @@ public interface MixinICommand extends ICommandWithPermission {
default void serverutilities$setModName(@NotNull String modName) {
commandOwners.put(getCommandName(), modName);
}

@Override
default boolean serverutilities$hasPermission(@NotNull EntityPlayerMP player) {
Event.Result result = Ranks.INSTANCE.getPermissionResult(player, serverutilities$getPermissionNode(), true);
if (result == Event.Result.DEFAULT) {
return canCommandSenderUseCommand(player);
}

return result == Event.Result.ALLOW;
}
}

0 comments on commit e820429

Please sign in to comment.