Mojang / brigadier

Brigadier is a command parser & dispatcher, designed and developed for Minecraft: Java Edition.
MIT License
3.44k stars 392 forks source link

Tree-Structure does not inherit generics #112

Open Placeblock opened 2 years ago

Placeblock commented 2 years ago

This problem is linked to this issue.

I tried implementing Brigadier, but if i try to create my argumentbuilder structure there is an exception. The problem is that the generic information of the CommandDispatcher isn't passed to the added child-argumentbuilder

You can simplify the problem to theese few lines of code:

public class Main {

    public static void main(String[] args) {
        Node.<String>node().addChild(
            Node.node().addChild(
                Node.node()
            )
        );
    }

    private static class Node<S> {
        public static <S> Node<S> node() {
            return new Node<>();
        }

        public Node<S> addChild(Node<S> node) {
            return this;
        }
    }
}

If i try to execute this i get a compiler error saying: error: incompatible types: Node<Object> cannot be converted to Node<String> Its obvious that my child node doesn't get the generic Type S from the root node and i think it is because of type erasure. I am using Java 17 and because brigadier is written in java 8 i changed my java version to 8 but it doesn't work too.

I just don't understand how it can work for all the other devs using brigadier, has somebody a solution for that?

portlek commented 2 years ago

https://github.com/Mojang/brigadier/issues/111#issuecomment-1186153886

Placeblock commented 2 years ago

I know that it works if you specify the generic type S in every single child, but this reduces code readability a lot if your generic type has many letters. In the examples given in the readme it works without specifying the generic type in every single child... i understand why it doesn't work but i wonder why it works for all the other people and devs using brigadier...

Veritaris commented 2 years ago

On new MC versions there are Commands.literal that u can use, not from Brigadier
I also find it too messy to call builder with types explicit writing so
As for me works well class I named BrigadierExtensions that contains the following code (commonly I use MC 1.7.10 so using ServerCommandSender works good to me):

public class BrigadierExtensions {
    public static LiteralArgumentBuilder<ServerCommandSender> literal(String name) {
        return LiteralArgumentBuilder.literal(name);
    }

    public static <T> RequiredArgumentBuilder<ServerCommandSender, T> argument(final String name, final ArgumentType<T> type) {
        return RequiredArgumentBuilder.argument(name, type);
    }
}

After I made this I had no need to declare my command and arguments explicitly before dispatcher.register() call
I suppose if you need extra methods that does not fit you can do same for them