Lamp icon indicating copy to clipboard operation
Lamp copied to clipboard

Command Resolution Issue: Sibling and Related Commands Not Properly Resolved in Split Command Registrations

Open lulu2002 opened this issue 1 year ago • 3 comments

I encountered an issue with the command resolution when using the help command in the current framework, which can resolve similar commands through SiblingCommands, ChildrenCommands, and their combination via RelatedCommands. However, this structure has a flaw when commands are registered separately across different classes.

For example, consider the following scenario:

In Class A:

@Command("base help")

In Class B:

@Command("base reward set")
@Command("base reward get")

In this case, the /base help command does not retrieve the base reward commands, because when checking the siblingPath, the path for base help is "base", while the path for base reward get is "base reward". As a result, neither siblingPath nor relativePath returns the full command help I expect.

Temporary Solution:

To resolve this issue temporarily, I implemented my own custom Help handler, using the following code:

Lamp<BukkitCommandActor> lamp = BukkitLamp.builder(this)
        .parameterTypes((it) -> {
            it.addParameterType(CardGroup.class, injector.getInstance(GroupParameterType.class));
            it.addContextParameterFactory(ContextParameter.Factory.forType(
                    MySiblingCommands.class,
                    (parameter, context) -> new MySiblingCommandsImpl(Collections.filter(context.command().lamp().registry().commands(), (anotherCmd) -> {
                        ExecutableCommand<BukkitCommandActor> currentCommand = context.command();
                        String currentPath = Temp.getSiblingPath(currentCommand).toLowerCase();
                        String anotherPath = Temp.getSiblingPath(anotherCmd).toLowerCase();
                        return anotherCmd != currentCommand && !anotherCmd.isSecret() && anotherPath.startsWith(currentPath) && anotherCmd.permission().isExecutableBy(context.actor());
                    }))
            ));
        })
        .build();

I also used the following helper to retrieve the sibling path:

object Temp {
    @JvmStatic
    fun getSiblingPath(cmd: ExecutableCommand<*>): String {
        val field = Execution::class.java.getDeclaredField("siblingPath")
        field.trySetAccessible()
        return field.get(cmd) as String
    }
}

This solution filters commands based on the siblingPath and uses startsWith to retrieve all related commands.

Request for Enhancement:

I believe it would be highly beneficial for the Lamp framework to natively support such functionality, allowing help commands to resolve all relevant commands, even when registered separately across different classes. This enhancement could improve the flexibility and ease of organizing command registration.

lulu2002 avatar Oct 11 '24 09:10 lulu2002

Thank you for bringing this to my attention. Yeah, I'm aware that the sibling implementation is not as comprehensive as it should. I think this goes back to the fact that we may not fully agree on who is a sibling of who :P

Nonetheless, the issue you point out is valid. I'll migrate this implementation when I get a chance. Thanks.

Revxrsal avatar Oct 11 '24 11:10 Revxrsal

We can agree that in this case help is a sibling of reward set, and I already told you this issue before

bed-dev avatar Oct 11 '24 12:10 bed-dev

Any updates on this? Running into issues using the Help.CommandList feature whilst migrating from v3 to v4, with CommandHelpWriter no longer available.

Using this feature simply shows pretty much every command it can find, and attempting to use the other options has the following results:

Help.RelatedCommands

Image

Help.ChildrenCommands

Image

Help.SiblingCommands

Image

instrumentalityi avatar Feb 12 '25 00:02 instrumentalityi