Skip to content
This repository has been archived by the owner on Nov 16, 2022. It is now read-only.

"provided" provider argument consuming arguments? #6

Closed
jonahseguin opened this issue Jan 14, 2018 · 7 comments
Closed

"provided" provider argument consuming arguments? #6

jonahseguin opened this issue Jan 14, 2018 · 7 comments
Assignees
Labels

Comments

@jonahseguin
Copy link

jonahseguin commented Jan 14, 2018

With my provider for a profile data object, it seems to be consuming an argument when it shouldn't be.

Here is my command:

@Command(aliases = "", desc = "Send a private message", usage = "<player> <message>", flags = "s")
    @Require("purified.commons.msg")
    public void execute(@Sender CommsPlayer player, @PTarget CommsPlayer target, @Text String message) {
        target.privateMsg(message, player);
    }

This is how I'm binding my providers:

 commandsManager.bind(CommsPlayer.class).annotatedWith(PTarget.class).toProvider(new CommsPlayerProvider());
 commandsManager.bind(CommsPlayer.class).annotatedWith(Sender.class).toProvider(new CommsPlayerSenderProvider());

This is my provider for the 'sender' impl:

public class CommsPlayerSenderProvider extends PCommandProvider<CommsPlayer> {

    @Override
    public boolean isProvided() {
        return true;
    }

    @Nullable
    @Override
    public CommsPlayer get(CommandArgs commandArgs, List<? extends Annotation> list) throws ArgumentException, ProvisionException {
        CommandSender sender = getFromNamespaceOrFail(commandArgs, CommandSender.class);
        if (!(sender instanceof Player)) {
            throw new CommandExitMessage("This is a player only command.");
        }
        Player player = (Player) sender;
        CommsPlayer commsPlayer = PurifiedCommons.getInstance().getCache().get(player);
        if (commsPlayer != null) {
            commsPlayer.msg("Args length: " +commandArgs.size());
            return commsPlayer;
        } else {
            throw new CommandExitMessage(ChatColor.RED + "For some reason, your commons profile is not cached and this command could not be performed.");
        }
    }

    @Override
    public List<String> getSuggestions(String s) {
        return PurifiedCommons.getInstance().getCache().getCache().values().stream()
                .map(commsPlayer -> commsPlayer.getPlayer().getName())
                .filter(s1 -> s1.toLowerCase().contains(s.toLowerCase()))
                .collect(Collectors.toList());
    }
}

and this is my provider for the 'target' impl (i.e should be first argument):

public class CommsPlayerProvider implements Provider<CommsPlayer> {

    @Override
    public boolean isProvided() {
        return false;
    }

    @Nullable
    @Override
    public CommsPlayer get(CommandArgs commandArgs, List<? extends Annotation> list) throws ArgumentException, ProvisionException {
        String name = commandArgs.next();
        return PurifiedCommons.getInstance().getCache().getByUsername(name);
    }

    @Override
    public List<String> getSuggestions(String s) {
        return PurifiedCommons.getInstance().getCache().getCache().values().stream()
                .map(commsPlayer -> commsPlayer.getPlayer().getName())
                .filter(s1 -> s1.toLowerCase().contains(s.toLowerCase()))
                .collect(Collectors.toList());
    }
}

Notice that for the sender, isProvided is true, but for the target isProvided is false.

However, in order for the command to execute with 'enough arguments' (i.e not reply with the error: missing argument for commsplayer), I have to type the command /msg Shawckz Shawckz hi
when it should be /msg Shawckz hi

I added a check in the sender provider to send me the args length, and upon performing "/msg Shawckz hi", it says that the commandArgs.size() == 0, when it should be 1?

Could this be with how I'm registering my commands (with the empty aliases = "")?

Very strange.

@xxyy

Update: upon changing my aliases from being empty to aliases = "msg", I get the expected behavior, however the command is now /msg msg Shawckz hi
when it should be /msg Shawckz hi
How should I go about registering commands like this? I don't want them all to be in the same class obviously. @xxyy

@literalplus
Copy link
Owner

literalplus commented Jan 14, 2018 via email

@jonahseguin
Copy link
Author

Sure.

Command:

public class CmdTest {

    @Command(aliases = "", desc = "Test command")
    @Require("purified.commons.test")
    public void executeTest(@Sender CommandSender sender, @OnlinePlayer Player player) {
        sender.sendMessage("Test: " + player.getName());
    }

}

Registering:

commandsManager.registerCommand(new CmdTest(), "test", "ptest");

Plugin loads with no errors.

image

Outcome of typing /test Shawckz

However, when typing /test Shawckz Shawckz
image

[12:52:30 INFO]: Shawckz issued server command: /test
[12:52:30 INFO]: Command exception: Too few arguments! No value found for parameter 'onlineplayer'
[12:52:32 INFO]: Shawckz issued server command: /test Shawckz
[12:52:32 INFO]: Command exception: Too few arguments! No value found for parameter 'onlineplayer'
[12:53:18 INFO]: Shawckz issued server command: /test Shawckz Shawckz

The first argument can be anything and it is ignored, i.e /test awdnauiowndw Shawckz or /test x Shawckz

But if I were to do /test Shawckz x:
image

@xxyy

@jonahseguin
Copy link
Author

Here is the relative maven repo/dependency, for reference:

    <repository>
            <id>xxyy-repo</id>
            <url>https://repo.l1t.li/xxyy-public/</url>
        </repository>
  <dependency>
            <groupId>li.l1t.common</groupId>
            <artifactId>intake-spigot</artifactId>
            <version>4.2.34</version>
            <scope>compile</scope>
        </dependency>

@jonahseguin
Copy link
Author

However, when I refactor the command so that there are no required arguments (just sender) like so:

public class CmdTest {

    @Command(aliases = "", desc = "Test command")
    @Require("purified.commons.test")
    public void executeTest(@Sender CommandSender sender) {
        sender.sendMessage("Test: " + sender.getName());
    }
}

I get the expected outcome:

>test
[12:59:03 INFO]: Test: CONSOLE

So I'm guessing this is not an issue with the 'sender' providers, but instead an issue with the 'target' providers consuming arguments twice?

This is only the case when registering with a blank alias though. When adding anything into the aliases = {"...", "..."}, it executes properly.

I'm guessing something with the way commands are registered into the commandmap and then instructed to consume arguments? I.e the way arguments are processed is not properly accounting for the fact that there is no alias, and it consumes something it shouldn't and passes it blank.

@xxyy

@jonahseguin
Copy link
Author

So when I refactor to this, adding an alias:
(making the command structure "/test sub")

public class CmdTest {

    @Command(aliases = "sub", desc = "Test command")
    @Require("purified.commons.test")
    public void executeTest(@Sender CommandSender sender, @OnlinePlayer Player player) {
        sender.sendMessage("Test: " + player.getName());
    }
}

I will get the expected outcome by typing /test sub Shawckz.

literalplus added a commit to literalplus/Intake that referenced this issue Jan 14, 2018
@literalplus literalplus self-assigned this Jan 14, 2018
@literalplus
Copy link
Owner

literalplus commented Jan 14, 2018

Thanks for the detailed explanation! I have been able to track this down to a bug in my modified Intake. I'll push a new release shortly, but will take a quick look at your other issue before while I have a test plugin set up :)

update: Here's the test plugin with the proof of concept: https://github.com/xxyy/intake-spigot-test/tree/master/src/main/java/li/l1t/test/intake . The new release has been published.

@jonahseguin
Copy link
Author

Thanks so much. Appreciate it!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants