4

I'm making a Spigot minecraft plugin with an API to allow other developers to hook into it. How can I create the API in a separate JAR file that will function the same as if it was in the plugin itself?

I need this because the plugin will not be openly distributed, but I need to allow access to certain methods/classes/objects within.

Desired outcome: Plugin.jar is running on the server. I have Plugin-API.jar sitting in a Maven repository for other developers to hook into that will allow interaction with plugin.jar.

I'm fairly new to creating my own APIs in general, so fully explained responses would be greatly appreciated. Thanks!

SpiroMarshes
  • 87
  • 1
  • 7
  • If the server is running Plugin.jar, you can create public methods inside its classes and allow devs to use them, importing them in their project. So you can have a `PluginAPI` class with the method `apiMethod()` inside Plugin.jar and it'll work as an API (you said that people will need your plugin running anyway) – LeoColman Mar 01 '17 at 15:32
  • The issue is that devs will not have access to the main Plugin.jar, which is why a separate PluginAPI JAR is essential. – SpiroMarshes Mar 01 '17 at 15:34
  • But Plugin.jar will be running on the server? If that's true, they already have access to the main Plugin.jar – LeoColman Mar 01 '17 at 15:34
  • Take as an example the ProtocolLib Library, it runs inside the server, but the same jar is used as the API – LeoColman Mar 01 '17 at 15:35
  • I can't use the same jar as the API, though. Plugin.jar is proprietary and not handed out to Developers, but we need a way for them to interact with it. I've seen it done the way I mentioned in my question before, but I can't remember where. – SpiroMarshes Mar 01 '17 at 15:40
  • I'm currently looking into Maven Submodules as suggested by a friend. – SpiroMarshes Mar 01 '17 at 15:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/136974/discussion-between-spiromarshes-and-kerooker). – SpiroMarshes Mar 01 '17 at 16:29

1 Answers1

5

Review

Allow me to rehash your question. You have a plugin - Special - whose distribution is limited/restricted for one reason or another). Instead, you want to provide a publicly available API - SpecialApi - to allow other developers to incorporate and/or use features provided by Special.

This is a common approach used by various plugins (e.g. Vault, Citizens2, PermissionsEx, etc.), though for different reasons than yours. The structural relationship of which is represented in the following component diagram.

enter image description here

Given that you mentioned submodules in the comments, let me digress for a moment as to why they may not be a good solution. A common use of submodules is to create a segregation of code based on some criteria. For example, a web application may be split functionally into modules for its GUI, business logic, data persistence, etc; whereas a “big data” service may have multiple modules segregating libraries for various techniques. A good example of modules in terms of plugins is PermissionsEx, which is split to support different target environments. It has one module containing common code; another module wrapping its core as a Bukkit plugin; and third module wrapping its core as a Sponge plugin.

Answer

Since your primary purpose is code isolation via an API, the easiest and most direct approach is to create two separate Maven projects – one for your plugin and one for your API.

SpecialApi Project

APIs should not be taken lightly. This may make more sense if you think of an API as a contract between you and developers that guarantees certain functionality. In short, keep these points in mind:

  • Once released, an API is a commitment
  • You should never remove functionality from an API
  • You can always add functionality to an API
  • You can change underlying code to your heart’s content provided it continues to implement the API

Your API project will define classes, interfaces, and data structures required to interface with your plugin. Do not make the mistake of making the API a plugin itself. You can certainly use SpigotAPI classes and interfaces, even to the point of defining a plugin class; however, it should never have to be loaded by Spigot. It is just a JAR that will be referenced as a provided dependency by others but also deployed as part of your actual plugin.

How you provide the API JAR is up to you. If you have some spare space on a public web server, you can manually create a small repository without having to consider using a service such as Nexus, Artifactory, etc.

Special Plugin Project

The plugin project contains everything else. You are free to add, change, correct, or remove internal components, provided it does not affect the API. It is a regular and normal plugin except that in addition to its resources, classes, and data normally provided, it also includes the same for your API; often referred to as a fat JAR. Otherwise, you would have to load your API separately as a plugin or as an additional entry on the server’s classpath. These last two options just beg for version and configuration management issues.

Instead, you use maven-assembly-plugin or similar tools to deliver plugin and API code in the same JAR. For example, this assembly configuration will combine any project dependency with a scope of compile into a single JAR.

    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4.1</version>
        <configuration>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
        </configuration>
        <executions>
            <execution>
                <id>make-assembly</id>
                <phase>package</phase> 
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

For anything more complex than this, you will want to look into maven-shade-plugin.

Frelling
  • 3,287
  • 24
  • 27