1

This has been something that I have always struggled with when starting new projects. So I decide to ask here and see what do you think would be the best way to structure this project, and hopefully I learn something from it.

This is the basic description of the project(I'm using Gradle btw and writing in Java).

I need to make a plugin that works on multiple platforms for example Spigot, Bungeecord and Velocity, all three have there own APIs that I need to use to make the plugin work with each platform. And the project is a announcer plugin that allows users to setup configurable announcers that would send messages to players connected to those servers.

My general thought process was to make:

  1. common module: where most of logic that can be applied to other three modules will be stored.
  2. spigot module: using logic form common module and shaping it so spigot can understand it.
  3. bungeecord module: using logic form common module and shaping it so bungeecord can understand it.
  4. velocity module: using logic form common module and shaping it so velocity can understand it.

Some of the things that project should have are:

  • Plugin main class that has logic loading and enabling the plugin(each API has its own class that extends main class for starting plugins).
  • File management class that would load up the configuration from a yaml files like messages for announcers, general settings(each API has its own class for reading yaml files).
  • Announcer builder and handling classes that would read announcer configuration file using file management classes and build announcers as object and handler that would send it to player etc.(each API has its own way of interacting with the players).
  • Command system that has the logic for command that would be executed by users and players(each API has its own logic for handling commands).

So my question is how would you structure this project with the least amount of repeatable code, duplicating classes that basically do same thing only a tiny bit differently for each API and maintain good code readability?

What I have right now is a working version for Spigot but it turned into a complete mess when I started adding support for Bungeecord.

EDIT: Example of one the more common problems I run into:

Spigot API has Bukkit class that has getServer() method that returns Server object. Bungeecord API has ProxiedServer class that has getInstance() method that returns ProxiedServer object.

And I have something like this:

public interface MyPlugin {

    ? getServer();
}

//extends JavaPlugin is required by Spigot API.
public class SpigotPlugin extends JavaPlugin implements MyPlugin {
    
    @Overrride
    public ? getServer() {
        return Bukkit.getServer();
    }
}

//extends Plugin is required by Bungeecord API.
public class BungeeCordPlugin extends Plugin implements MyPlugin {
 
    @Overrride
    public ? getServer() {
        return ProxiedServer.getInstance();
    }
}

What do it need to put instead of ? to get the right server instance(I cant edit ProxiedServer or Bukkit classes)?

Lynx
  • 105
  • 9
  • The numbered items sound like a good start for the modules, where 2 through 4 are vertical slices. I'm not sure what _complete mess_ means, but the adapter pattern might help. There should be no duplicate code. – Andrew S Nov 25 '20 at 21:37
  • By mess I mean I have methods that take `Object` as parameter and then cast it to the required object based on the platform the plugin is running, so result from that is a lot of casting. I don't quite like that approach and I'm not sure if that's how it should be done. Ill check out the adapter pattern thanks for the suggestion. – Lynx Nov 25 '20 at 21:51
  • That's where the adapter pattern can be helpful. A common class is wrapped by a platform specific class. A platform class knows how to interact with its platform, but uses the common class to get the data. – Andrew S Nov 25 '20 at 21:58

1 Answers1

0

This is a few months old but in the interest of archives and future searchers I would like to offer this: Yes, you can return a generic Type something like this:

@Overrride
public <T> getServer() {
    return plugin.getInstance();
}

For reference: https://stackoverflow.com/a/31239655/10793514

And more information on generics: https://www.baeldung.com/java-generics#generic-methods