Repository navigation
(Outdated v5) API
This guide is for versions 5 and below; please see the updated API Guide
CoordinateOffset offers an API so that other plugins can interact with it. With it, you can:
- Get the current offset of a player so your plugin can (for example) send meaningful coordinates in messages
- Define your own offset providers to customize exactly how offsets are applied
Prefer an example? Check out the example-api-plugin in this repository.
Add the CoordinateOffset API dependency:
// build.gradle.kts
repositories {
mavenCentral() // For latest release
maven("https://central.sonatype.com/repository/maven-snapshots/") // For snapshots
}
dependencies {
// Pick one option; do not shade the API into your plugin
compileOnly("com.jtprince.coordinateoffset:coordinateoffset-api:v5.0.0")
compileOnly("com.jtprince.coordinateoffset:coordinateoffset-api:v5.0.1-SNAPSHOT")
}Add CoordinateOffset as a dependency to your plugin:
# plugin.yml
depend: [ CoordinateOffset ] # Make CoordinateOffset a required plugin
softdepend: [ CoordinateOffset ] # Make CoordinateOffset optional# paper-plugin.yml
dependencies:
server:
CoordinateOffset:
load: BEFORE
required: true # or falseAll accesses to the API are done through a singleton CoordinateOffsetAPI object. Get the singleton object through CoordinateOffset.api().
import com.jtprince.coordinateoffset.api.CoordinateOffset;
import com.jtprince.coordinateoffset.api.CoordinateOffsetAPI;
CoordinateOffsetAPI coApi;
try {
coApi = CoordinateOffset.api();
} catch (NoClassDefFoundError e) {
// CoordinateOffset is not installed.
// Handle this case if you are making CoordinateOffset an optional dependency.
}CoordinateOffset has an adapter layer to individual platforms, like Paper. Adapt any Player objects to an OffsetPlayer for use with the API.
org.bukkit.entity.Player player = /* ... */;
OffsetPlayer coPlayer = coApi.adaptPlayer(player);
Offset offset = coApi.getOffset(coPlayer);Apply the offset to a Bukkit Location to determine which coordinates the Player sees:
org.bukkit.Location realBlockLocation = /* ... */.getLocation();
org.bukkit.Location locationPlayerSees = offset.apply(realBlockLocation);
/* ... */.getPlayer().sendMessage("You see coordinates " + locationToString(locationPlayerSees) + ".");
/* ... */.getPlayer().sendMessage("The real coordinates of that thing are " + locationToString(realBlockLocation) + ", but you might not know that!");Or reverse the offset if you're parsing a location that a Player entered:
org.bukkit.Location locationPlayerSees = parseMessage(/* ... */);
org.bukkit.Location realLocation = offset.unapply(locationPlayerSees);To define offsets more flexibly than providers in config.yml, you can implement your own OffsetProvider class. A complete example is available here.
Register your provider in your plugin's onEnable. You must pass a deserialize function (see example below) so that CoordinateOffset knows how to parse your provider in config.yml.
public void onEnable() {
CoordinateOffset.api().registerOffsetProviderClass("MyCustomOffsetProvider", MyCustomOffsetProvider::deserialize);
}Implement your provider and a deserialize function:
import com.jtprince.coordinateoffset.provider.*;
public class MyCustomOffsetProvider extends OffsetProvider {
public MyCustomOffsetProvider(String userDefinedProviderName) {
super(userDefinedProviderName);
}
@Override
public Offset provideOffset(OffsetProviderContext context) {
// Put your offset generation logic here. "context" provides a player, world, location, etc.
int x = /* ... */;
int z = /* ... */
return new Offset(x, z);
return Offset.ZERO;
return Offset.random(12345); // Randomize each component between +/- the provided parameter
return Offset.align(x, z); // Round components to multiples of 16 (CO throws an exception if they aren't)
}
public static MyCustomOffsetProvider deserialize(OffsetProviderConfig config) {
// Implement config parsing here. Or, to keep things simple with no config, just return.
return new MyCustomOffsetProvider(config.getUserDefinedProviderName());
}
@Override
public SequencedMap<String, *> serialize() {
// Implement the reverse of your deserialize logic here. If not parsing config, just return.
return new LinkedHashMap<String, Object>();
}
}Apply your new provider. It will not be active unless configured in the CoordinateOffset configuration.
# plugins/CoordinateOffset/config.yml
defaultOffsetProvider: myCustomProvider
offsetProviders:
myCustomProvider:
class: MyCustomOffsetProvider