Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Simple Plugin System #972

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

MagicLu550
Copy link

@MagicLu550 MagicLu550 commented Nov 24, 2019

Please read the full description

No cancellation of the original plugin system, still compatible with all previous plugins

Has been tested and is working fine, the command can also run normally

You can develop the nukkit plugin without using plugin.yml and it is compatible with the original plugin system.

This system will trigger without plugin.yml

the log:

luchangcundeMacBook-Pro:nukkit luchangcun$ java -jar nukkit.jar
08:24:04 [INFO ] Welcome! Please choose a language first!
08:24:04 [INFO ] eng => English
08:24:04 [INFO ] chs => 中文(简体)
08:24:04 [INFO ] cht => 中文(繁體)
08:24:04 [INFO ] jpn => 日本語
08:24:04 [INFO ] rus => Pyccĸий
08:24:04 [INFO ] spa => Español
08:24:04 [INFO ] pol => Polish
08:24:04 [INFO ] bra => Português-Brasil
08:24:04 [INFO ] kor => 한국어
08:24:04 [INFO ] ukr => Українська
08:24:04 [INFO ] deu => Deutsch
08:24:04 [INFO ] ltu => Lietuviškai
08:24:04 [INFO ] idn => Indonesia
08:24:04 [INFO ] cze => Czech
08:24:04 [INFO ] tur => Turkish
08:24:04 [INFO ] fin => Suomi
> eng
08:24:07 [INFO ] Loading nukkit.yml ...
08:24:07 [INFO ] Loading server.properties ...
08:24:07 [INFO ] Selected English (eng) as the base language
08:24:07 [INFO ] Starting Minecraft: BE server version v1.12.0
08:24:07 [INFO ] Selected Zlib Provider: 2 (cn.nukkit.utils.ZlibThreadLocal)
08:24:07 [INFO ] Opening server on 0.0.0.0:19132
08:24:07 [INFO ] This server is running Nukkit version git-445feb6 "" (API 1.0.9)
08:24:07 [INFO ] Nukkit is distributed under the LGPL License
08:24:07 [INFO ] Loading recipes...
08:24:07 [INFO ] Loaded 1301 recipes.
08:24:07 [INFO ] Successfully loaded 0 resource packs
08:24:07 [INFO ] Loading hello v0.0.1
08:24:07 [INFO ] [hello] 2333
08:24:07 [INFO ] Preparing level "world"
08:24:07 [INFO ] Epoll Status is false
08:24:07 [INFO ] Preparing level "nether"
08:24:07 [INFO ] Enabling hello v0.0.1
08:24:07 [INFO ] [hello] 2333
08:24:07 [INFO ] Starting GS4 status listener
08:24:07 [INFO ] Setting query port to 19132
08:24:07 [INFO ] Query is running on 0.0.0.0:19132
08:24:07 [INFO ] Default game type: Survival Mode
08:24:07 [INFO ] Done (3.144s)! For help, type "help" or "?"
> hello
08:24:11 [INFO ] [hello] hello,world
> 

The simple plug-in system is made to simplify plug-in development and reduce plug-in development coupling and reduce plug-in maintenance costs. It will make the plug-in more organized and easier to migrate and modify.

Simple plugin system is composed of 7 annotations and can be used with plugin.yml at the same time

  • @main main class positioning annotation. With this annotation, you can locate the main class and load configuration parameters without writing plugin.yml.
  • @command defines a command, which will be explained later in two ways
  • @Permission used with Command, which will be explained later
  • @children used in children member of Permission
  • @EnableRegister Enable automatic registration of the listener, you can use it without manual registration, the listener registration is automatically completed by nukkit
  • @EnableCommand Same as above, here is the command auto registration, fallBackPrefix is the plugin name
  • @autoplugin injects the main class object, making it easy to use the main class object elsewhere

All features here have been tested and working properly, no matter for other plugins

How to use SimplePlugin

SimplePlugin is created to simplify the development of plug-ins and coexist with the original plug-in system. When the plug-in does not have plugin.yml, it will launch the plug-in format of SimplePlugin.
Of course, if you still use plugin.yml (that is, without the @main annotation), you can also use any of them (except @main)

  1. First make sure the plugin does not have a plugin.yml file
  2. Mark the main class
    SimplePlugin relies on reflection to implement automatic scanning of the main class, which is determined by @main annotation
package net.noyark.www;

import cn.nukkit.command.CommandSender;
import cn.nukkit.plugin.PluginBase;
import cn.nukkit.plugin.simple.*;

@Main(name="hello",api="1.0.9")
public class Example extends PluginBase{

    private static Example plugin;


    @Override
    public void onLoad() {
        this.getLogger().info("2333");
    }

    @Override
    public void onEnable() {
        plugin = this;
        this.getLogger().info("2333");
    }

    public static Example getPlugin() {
        return plugin;
    }

}

@main has a lot of options

String name();

String version() default "0.0.1";

String author() default "";

String[] api();

String[] depend() default {};

String[] loadBefore() default {};

String[] softDepend() default {};

String description() default "";

String load() default "POSTWORLD";

String website() default "";

String prefix() default "";

Command[] commands() default {};

Permission[] permissions() default {};
  1. Simplified instructions
    Simplified instructions provide multiple ways
    1. Method, its advantage is to make the instructions more organized, and support multiple parameters and single parameters
package net.noyark.www;

import cn.nukkit.command.CommandSender;
import cn.nukkit.plugin.PluginBase;
import cn.nukkit.plugin.simple.*;

@Main(name="hello",api="1.0.9")
@EnableRegister(noRegister = {
        ABListener.class
})
public class Example extends PluginBase{

    private static Example plugin;

		//单参数
    @Command(
            name="hello",
            permission = "hello.test"
    )
    @Permission(
            permission = "hello.test",
            theDefault = "op"
    )
    public boolean onHello(SimpleCommandData data){
        CommandSender sender = data.getSender();
        this.getLogger().info(sender.getName());
        return true;
    }


    @Override
    public void onLoad() {
        this.getLogger().info("2333");
    }

    @Override
    public void onEnable() {
        plugin = this;
        this.getLogger().info("2333");
    }

    public static Example getPlugin() {
        return plugin;
    }

}

Multiple parameters

@Command(
        name="hello",
        permission = "hello.test"
)
@Permission(
        permission = "hello.test",
        theDefault = "op"
)
public boolean onHello(CommandSender sender, cn.nukkit.command.Command command, String label, String[] args){
    
    this.getLogger().info(sender.getName());
    return true;
}
2. Main class confirmation: Mark the command on the main class
@Main(name="hello",api="1.0.9",commands = {
        @Command(name="abc",permission = "a.b")
},permissions = {
        @Permission(permission = "a.b",theDefault = "op")
})
public class Example extends PluginBase{
  1. Automatically register the listener
    Realize automatic listener registration, of course, you can choose which auto and which need, the listener will automatically register after onEnable, use @EnableRegister method
@EnableRegister(noRegister = {
        ABListener.class
})
//It will scan all listeners and register, but will not be registered in noRegister
public class Example extends PluginBase{
  1. AutoPlugin annotation
    You can directly get the main class object through this annotation

such as

public class MyCommand extends Command {

    @AutoPlugin
    private Plugin plugin;
//Provided that the object is automatically registered
//Only this annotation is needed to get the main class object
    public MyCommand() {
        super("hello","一个测试指令");
    }

    @Override
    public boolean execute(CommandSender commandSender, String label, String[] strings) {
        plugin.getLogger().info("233");
        return true;
    }
}

Thanks for adoption

@wode490390
Copy link
Contributor

I think plugin.yml is essential for a plugin. It allows you to quickly identify whether a Jar is a plugin, and you can browse it to get some basic information about a plugin.
If you just don't want to fill out plugin.yml, take a look at the Plugin Annotations project. Plugin Annotations is a tool created to help developers who find it tedious to make and fill out a plugin.yml file every time they create a new project.

@MagicLu550
Copy link
Author

I think plugin.yml is essential for a plugin. It allows you to quickly identify whether a Jar is a plugin, and you can browse it to get some basic information about a plugin.
If you just don't want to fill out plugin.yml, take a look at the Plugin Annotations project. Plugin Annotations is a tool created to help developers who find it tedious to make and fill out a plugin.yml file every time they create a new project.

Well, you're right. But I'm trying to provide another way that can be accepted by people. Also, for those who doesn't know PluginAnnotations, it's convenient, isn't it?

}
}

return null;
}

//simple load Plugin
@Override
public Plugin simpleLoadPlugin(File file) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the core part of loading the simple plugin, initializing the plugin information.

@hteppl
Copy link

hteppl commented Nov 24, 2019

Useless...

Copy link
Author

@MagicLu550 MagicLu550 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless...

Um.... This is an unusual design... It’s normal to not be accepted, why not try it? You may have different ideas, thank you very much!

return simpleLoadPlugin(new File(fileName));
}

private Class getSimplePlugin(File file){
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get and complete the auto-enrollment section

@Redned235
Copy link
Member

I think an annotation plugin system could be cool, but as mentioned earlier with the way you've set it up, I personally do not believe this is the right approach. Imo, this kind of stuff should be done by an annotation processor instead.

@zzz1999
Copy link

zzz1999 commented Nov 25, 2019

In my opinion,it is significant of plugin design mode improve.Admittedly,Someone feels it break up what they framework or custom of plugin.Notheless annotation are still decline green hand's difficultly of introduction and provide a way to avoid some wrong.
All in all,I keen it.If you think it wried,you can hold plugin.yml .It will not abolish anyway.

@YorokobiMaster
Copy link

Hello? I don't know why you guys don't believe it, but it's providing a brand new way that efficient and convenient, and it has NO EFFECT on plugin.yml.

@Redned235
Copy link
Member

Hello? I don't know why you guys don't believe it, but it's providing a brand new way that efficient and convenient, and it has NO EFFECT on plugin.yml.

I’m not saying this is a bad idea (I actually like the idea believe it or not), it’s more or less the way it’s being executed. Using an annotation processor allows for this system to still be in place, but also allows for the plugin.yml to be created.

The project wode mentioned earlier does this well, and I believe that’s the better way for this annotation system to work.

@MagicLu550
Copy link
Author

MagicLu550 commented Nov 29, 2019

Hello? I don't know why you guys don't believe it, but it's providing a brand new way that efficient and convenient, and it has NO EFFECT on plugin.yml.

I’m not saying this is a bad idea (I actually like the idea believe it or not), it’s more or less the way it’s being executed. Using an annotation processor allows for this system to still be in place, but also allows for the plugin.yml to be created.

The project wode mentioned earlier does this well, and I believe that’s the better way for this annotation system to work.

Thank you,I respect your opinion.But...
In fact, my solution still retains the plugin.yml system, and my annotations were finally made based on this system, but the process of generating plugin.yml in the middle was omitted. Compared to the later generation of plugin.yml, I feel more convenient and faster.

You can just use it as a tool to simplify development, it is not intended to replace this system
And it is more convenient to modify, and the coupling degree is smaller, which makes future projects more convenient to maintain. If I simply translate the annotations to plugin.yml, I think that it will lose its original intention.

In terms of instructions, I use redirection so that I don't need to judge the command through "if", and maintenance in the later period makes the code more conditioning.

On the listener, the automatic registration method can more easily add and cancel the listener.

The benefits are:
Registering the listener only needs to be defined, there is no need to register it manually.
For the processing of the PluginCommand method, only two annotations are required. There is no need to complicated file definition and judge in onCommand
Reduced the complexity of plug-in configuration. It is done together in the main class. Changing the main class only needs to replace @main into another class.

And I Add Something

Of course, if you still use plugin.yml (that is, without the @main annotation), you can also use any of them (except @main)

Others

You can use the AutoPlugin annotation to inject objects of the main class, which was recently added based on a simple plugin system

package net.noyark.www;

import cn.nukkit.command.Command;
import cn.nukkit.command.CommandSender;
import cn.nukkit.plugin.Plugin;
import cn.nukkit.plugin.simple.AutoPlugin;


public class MyCommand extends Command {

    @AutoPlugin
    private Plugin plugin;
    public MyCommand() {
        super("hello01","test");
    }

    @Override
    public boolean execute(CommandSender commandSender, String label, String[] strings) {
        plugin.getLogger().info("233");
        return true;
    }
}

Of course, this is just my personal opinion.
Thanks for exploring.

@ghost
Copy link

ghost commented Jan 3, 2020

I like the ideea and how it is looking, but i think will be a perfect way to just rewrite all plugin section and make another PR.

I like your addons, but now code is too much and it's not cleaned up. My recommandation, as 5 years player of minecraft (or maybe much more) and 3 years of programming minecraft, i suggest you to clean up all and remake plugin system. Thank you for all. I think @SupremeMortal and @Creeperface01 is agree with me.

If you can do that, you are a really good man and implicated, what i like on people.

@MagicLu550
Copy link
Author

I like the ideea and how it is looking, but i think will be a perfect way to just rewrite all plugin section and make another PR.

I like your addons, but now code is too much and it's not cleaned up. My recommandation, as 5 years player of minecraft (or maybe much more) and 3 years of programming minecraft, i suggest you to clean up all and remake plugin system. Thank you for all. I think @SupremeMortal and @Creeperface01 is agree with me.

If you can do that, you are a really good man and implicated, what i like on people.

OK,I will do it when I have time

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

Successfully merging this pull request may close these issues.

None yet

6 participants