Skip to content
Select theme
  • Auto
  • Dark
  • Light
Download

Getting started

The API is one small jar, com.oasis:oasis-api. It holds interfaces and a few records and enums. The Oasis plugin on the server holds the code behind them, so your plugin compiles against the jar and Oasis provides it at runtime.

The API needs Java 21 or newer and Paper 1.21.11 or newer.

  1. Add the repository and the dependency.

    The API is on the Oasis Maven repository, https://telesphorepo.com/maven/oasis/. The current version is 3.0-SNAPSHOT.

    build.gradle.kts
    repositories {
    maven("https://repo.papermc.io/repository/maven-public/")
    maven("https://telesphorepo.com/maven/oasis/")
    }
    dependencies {
    compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT")
    compileOnly("com.oasis:oasis-api:3.0-SNAPSHOT")
    }
  2. Keep the API out of your jar.

    Use compileOnly in Gradle and provided in Maven, as above. Never shade or relocate the API into your plugin. Oasis provides those classes on the server, and a second copy in your jar is a different class to Java. Oasis would not recognize it, and Oasis.api(this) would fail.

  3. Declare Oasis in your plugin file.

    Oasis must enable before your plugin, so the API is ready in your onEnable. Use depend when your plugin can’t run without Oasis, and softdepend when Oasis is optional.

    plugin.yml
    name: GriefRevert
    version: 1.0.0
    main: com.example.griefrevert.GriefRevert
    api-version: '1.21.11'
    # Oasis is required:
    depend: [Oasis]
    # Or, when Oasis is optional:
    # softdepend: [Oasis]

    A Paper plugin needs join-classpath: true. Without it, your plugin can’t load the com.oasis.api classes even when Oasis runs.

  4. Get the API in onEnable.

    Ask for the API once, with your own plugin, and keep it in a field.

    package com.example.griefrevert;
    import com.oasis.api.Oasis;
    import com.oasis.api.OasisApi;
    import org.bukkit.plugin.java.JavaPlugin;
    public final class GriefRevert extends JavaPlugin
    {
    private OasisApi oasis;
    @Override
    public void onEnable()
    {
    oasis = Oasis.api(this);
    }
    }

    Oasis.api(this) throws IllegalStateException when Oasis is not enabled. With depend, Paper doesn’t enable your plugin without Oasis, so that only happens when Oasis itself failed to start.

    The API you get acts for your plugin. See What the API acts for.

With softdepend, your plugin also runs on servers without Oasis. On those servers the com.oasis.api classes are not on the classpath at all. Java loads a class the first time your code needs it, so any code that names an Oasis type throws NoClassDefFoundError when it runs, or when Java loads the class that holds it.

The safe pattern is to keep every Oasis reference in one class of your own, and to load that class only after you check that Oasis is enabled. Your main class names only that class, never an Oasis type.

OasisHook.java
package com.example.softdepend;
import com.oasis.api.Cause;
import com.oasis.api.Oasis;
import com.oasis.api.OasisApi;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
/** Every Oasis call of the plugin. Nothing else in the plugin imports com.oasis.api. */
final class OasisHook
{
private final OasisApi api;
OasisHook(Plugin plugin)
{
api = Oasis.api(plugin);
}
void placed(Player player, BlockState before, BlockState after)
{
api.logger().by(player).block(Cause.PLACING, before, after);
}
}
SoftDepend.java
package com.example.softdepend;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public final class SoftDepend extends JavaPlugin
{
/** Null when Oasis is not on the server. */
private OasisHook oasis;
@Override
public void onEnable()
{
if (getServer().getPluginManager().isPluginEnabled("Oasis"))
{
oasis = new OasisHook(this);
getLogger().info("Oasis found. Edits of this plugin go into its history.");
}
}
/** Called by the rest of the plugin, with or without Oasis. */
public void logPlacement(Player player, BlockState before, BlockState after)
{
if (oasis != null)
{
oasis.placed(player, before, after);
}
}
}

A field or a variable of type OasisHook is safe, because Java loads OasisHook only when the code first creates one or calls it. Keep these rules:

  • No com.oasis.api import in the main class, or in any class that loads when Oasis is missing.
  • No Oasis type in a field, a parameter, a return type, a lambda or a method reference of those classes.
  • Register an Oasis event listener from inside the hook class, after the check. A listener class names the event type, so it must not load on a server without Oasis.

Oasis publishes a sources jar and a Javadoc jar beside the API jar. Your IDE shows the Javadoc of every method as you type, and the Javadoc states the same rules as these pages: the thread of each callback, what throws, and what each value means.

IntelliJ IDEA downloads the sources for a Gradle project on its own. In a Maven project, click Download Sources in the editor banner, or run mvn dependency:sources.