At first you need to create two classes, the first is a registry class which for registering commands and listeners.
public class TesterRegistry implements ComponentsRegistry {
@Override
public void registerCommand(CommandRegistry commandRegistry) { // register command
}
@Override
public void registerListeners(ListenerRegistry listenerRegistry) { //register listeners
}
}
The second if a lifecycle class which to replcae the feature of JavaPlugin (to injectable lifecycle instance)
public class TesterLifeCycle implements ELDLifeCycle {
@Override
public void onEnable(JavaPlugin javaPlugin) {
javaPlugin.getLogger().info("hello world!"); // output hello world!
}
@Override
public void onDisable(JavaPlugin javaPlugin) {
javaPlugin.getLogger().info("plugin disabled!"); //output plugin disabled!
}
}
LifeCycle class and Registry class must be no arg constructor.
Start to create your main class.
@ELDPlugin(
registry = TesterRegistry.class, //point to registry class
lifeCycle = TesterLifeCycle.class //point to lifecycle class
)
public class ELDTester extends ELDBukkitPlugin {
@Override
protected void bindServices(ServiceCollection serviceCollection) {
// the place to bind service, bind singleton and add configuration
}
@Override
protected void manageProvider(ManagerProvider provider) {
// operation before lifecycle
}
}
Finally, create plugin.yml and point your main into your class which extended ELDBukkitPlugin, then your first plugin will be done.
Command Creation
Below examples showing how to create sub commands
@Commander(
name = "test",
description = "test command",
alias = {"tes", "te"}
)
public class TestCommand implements CommandNode {
@Override
public void execute(CommandSender commandSender) {
}
}
@Commander(
name = "one",
description = "test one command"
)
public class TestOneCommand implements CommandNode {
//command arg, the display name will be "string"
//command order is 0
@CommandArg(order = 0, labels = {"string"})
private String value;
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage("this is one command with value "+value);
}
}
@Commander(
name = "two",
description = "two command"
)
public class TestTwoCommand implements CommandNode {
@CommandArg(order = 0)
private int number;
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage("this is two command with number "+number);
}
}
Finally, define the parent-child relationship from registry class.
TesterRegistry.java
public class TesterRegistry implements ComponentsRegistry {
@Override
public void registerCommand(CommandRegistry commandRegistry) {
commandRegistry.command(TestCommand.class, c -> {
c.command(TestOneCommand.class);
c.command(TestTwoCommand.class);
});
}
@Override
public void registerListeners(ListenerRegistry listenerRegistry) {
}
}
Event Listener (ELD ver)
You can instantly register bukkit listener into your registry class, but you can also register an eld listener which shows like below.
@Resource(locate = "config.yml") // resource location from both inside jar and outside destination
public class TestConfig extends Configuration {
public String name;
public int number;
public boolean bool;
public Box box;
public static class Box {
public String name;
public int size;
public ChatColor color;
@Override
public String toString() {
return "Box{" +
"name='" + name + '\'' +
", size=" + size +
", color=" + color +
'}';
}
}
@Override
public String toString() {
return "TestConfig{" +
"name='" + name + '\'' +
", number=" + number +
", bool=" + bool +
", box=" + box +
'}';
}
}
This framework are using jackson-databind-yaml as based,so you can use any jackson-annotations to control your mapper object.
You can inject the mapping object after registration.
Instance injection
Injecting yaml mapping object
example from sub commands
@Commander(
name = "config",
description = "config command"
)
public class TestConfigCommand implements CommandNode {
@Override
public void execute(CommandSender commandSender) {
}
}
@Commander(
name = "edit",
description = "config edit command"
)
public class TestConfigEditCommand implements CommandNode {
private final Random random = new Random();
@Inject //inject config
private TestConfig config;
@Override
public void execute(CommandSender commandSender) {
config.bool = random.nextBoolean();
config.name = UUID.randomUUID().toString();
config.number = random.nextInt();
config.box = new TestConfig.Box();
config.box.color = ChatColor.values()[random.nextInt(ChatColor.values().length)];
config.box.name = UUID.randomUUID().toString()+" box";
config.box.size = random.nextInt();
try {
config.getController().save();
commandSender.sendMessage("save completed");
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Commander(
name = "reload",
description = "config reload command"
)
public class TestConfigReloadCommand implements CommandNode {
@Inject // inject config
private TestConfig config;
@Override
public void execute(CommandSender commandSender) {
config.getController().reload();
commandSender.sendMessage("reload completed");
}
}
example from listeners
public class TestListeners implements Listener {
@Inject // inject config
private TestConfig config;
@EventHandler
public void onPlayerChat(AsyncPlayerChatEvent e) {
if (e.getMessage().equals("config")) {
e.getPlayer().sendMessage(config.toString());
}
}
}
Injecting your own singleton
public class TesterSingleton {
private final Map<String, String> collection = new HashMap<>();
public void setKey(String key, String value){
this.collection.put(key, value);
}
public String getString(){
return this.collection.toString();
}
}
public class TesterLifeCycle implements ELDLifeCycle {
@Inject
private TesterSingleton singleton;
@Inject
private TestConfig config;
@Override
public void onEnable(JavaPlugin javaPlugin) {
singleton.setKey("abc", "foo");
singleton.setKey("xyz", "bar");
javaPlugin.getLogger().info(singleton.getString());
javaPlugin.getLogger().info(config.toString());
}
@Override
public void onDisable(JavaPlugin javaPlugin) {
javaPlugin.getLogger().info(singleton.getString());
javaPlugin.getLogger().info(config.toString());
}
}
@Inject can also use in constructor.
public class TestManager {
private final TesterSingleton singleton;
@Inject
public TestManager(TesterSingleton singleton){
this.singleton = singleton;
singleton.setKey("start", "started a insertion in constructor");
}
public void doSomething(){
System.out.println(singleton.getString())
}
}
You can't use @inject on uninjectable instance or it will throw an error.
Injecting Service
Services and Singleton are different that services are using interface while singleton are using instance. Using interface can avoid the high coupling problem and commonly use for API, or with different implementations.
@Commander(
name = "one",
description = "one scheduler"
)
public class TestSchedulerOneCommand implements CommandNode {
@Inject
private ScheduleService service; // this is a service from framework
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage("wait for 5 secs");
service.injectTask(new BukkitRunnable() {
@Inject
private ScheduleService service;
@Override
public void run() {
commandSender.sendMessage("scheduler service instance inside bukkit runnable is "+(service == null ? "null" : "not null !"));
}
}).asynchronous(false)
.timeout(100L)
.run(ELDTester.getProvidingPlugin(ELDTester.class));
}
}
You can inject instance from any instance which allow injection.
injectable instances as below
yaml mapping object
Service
Singleton
instance which allow injection as below
Command (which extended Command Node)
Listeners (which extended Listener or ELDListener)
Singleton (which registered from ServiceCollection)
Services (which registered from ServiceCollection)