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

Developer API

Oasis has a Java API for other Paper plugins. With it, your plugin can:

  • Log its own edits. When your plugin changes blocks, moves items or spawns entities, log them. Staff can then look them up and roll them back like anything a player did.
  • Read history. Ask for the edits a player made, the edits in an area, the whole history of one block, or the positions an operation kept, a page at a time.
  • Run rollbacks, restores and undos. Start the same operations staff run with /rollback, /rs and /undo, follow their progress, and read what they did.
  • Purge history. Delete edits for good, the same way /oasis purge does, even in a world that is not loaded.
  • Read and clear incidents. List the problems the store recorded, and clear them, as /oasis incidents does.
  • Load the worlds it keeps. Give Oasis a loader for worlds in your plugin’s own storage, such as slime worlds, so a rollback can write into them while they are not loaded.
  • React to operations and purges. Listen for the end of every operation and every purge, and for each chunk an operation rewrites, whoever started it.

The API lives in one package, com.oasis.api, and its events live in com.oasis.api.event. Everything else in the Oasis jar is internal and can change at any time.

This plugin asks for the API when it starts. Its revert method shows a staff member the newest edit a player made in the last hour, then rolls back that hour and reports the result.

package com.example.quickstart;
import com.oasis.api.Edit;
import com.oasis.api.Oasis;
import com.oasis.api.OasisApi;
import com.oasis.api.Selection;
import java.time.Duration;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public final class QuickStart extends JavaPlugin
{
private OasisApi oasis;
@Override
public void onEnable()
{
// Oasis is in `depend` of plugin.yml, so it is enabled before this runs.
oasis = Oasis.api(this);
}
public void revert(Player staff, OfflinePlayer griefer)
{
Selection lastHour = Selection.all().by(griefer).within(Duration.ofHours(1));
oasis.lookups().find(lastHour, 1).thenAccept(page ->
{
if (page.items().isEmpty())
{
staff.sendMessage(griefer.getName() + " made no edits in the last hour.");
return;
}
Edit newest = page.items().getFirst();
staff.sendMessage("Newest edit: " + newest.cause().word() + " " + newest.after() + " at "
+ newest.position().x() + " " + newest.position().y() + " " + newest.position().z());
oasis.operations().rollback(lastHour)
.requestedBy(staff)
.audience(staff)
.start()
.result().thenAccept(result ->
staff.sendMessage("Rolled back " + result.applied() + " edits. Kept " + result.kept() + "."));
});
}
}

Every future in the API completes on the main thread, so both callbacks can send messages and touch the world. Because the request names staff as its audience, the staff member also sees the start line, the progress bar and the summary, just as for a command.

If you build with an AI coding agent, give it the API pages as plain text, or install the oasis-api skill. See For AI agents.