API for developers

EndlessVehicles' API lets another plugin read and use every feature: vehicles, garages, fuel, models, the shop and events.

Adding the dependency

The endlessvehicles-api module only contains interfaces, records, enums and events: the implementation lives in the plugin. Declare it as provided (it must not be bundled in your jar), and your plugin's plugin.yml needs a depend (or softdepend) on EndlessVehicles.

Maven

<repositories>
  <repository>
    <id>endless</id>
    <url>https://endlesshorizons.it/maven</url>
  </repository>
</repositories>

<dependencies>
  <dependency>
    <groupId>it.endlesshorizons.endlessvehicles</groupId>
    <artifactId>endlessvehicles-api</artifactId>
    <version>1.0.0</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

Gradle

repositories {
    maven { url = uri("https://endlesshorizons.it/maven") }
}

dependencies {
    compileOnly("it.endlesshorizons.endlessvehicles:endlessvehicles-api:1.0.0")
}

plugin.yml

name: MyPlugin
main: com.example.MyPlugin
api-version: '1.21'
depend: [EndlessVehicles]

How to use it

Get the API with EndlessVehiclesApi.get() (once EndlessVehicles is active, for example in your own onEnable). With EndlessVehiclesApi.find() you get an Optional instead of an exception.

EndlessVehiclesApi api = EndlessVehiclesApi.get();

// the vehicle a player is driving
api.vehicles().getRiddenBy(player.getUniqueId()).ifPresent(vehicle ->
        player.sendMessage(vehicle.plate() + ": " + vehicle.fuelLiters() + " L"));

// give a vehicle to a garage
GiveResult result = api.vehicles().give("police", "crown_victoria", null, false, GiveSource.COMMAND);
if (result.isOk()) {
    api.fuel().addFuel(result.vehicleId(), 20);
}

// sell a vehicle to a player (payments go through Vault)
PurchaseResult bought = api.shop().buy(player, "offroad_black", new VehicleColor(200, 30, 30), null, false);

The services

ServiceWhat it does
api.vehicles()Reading a vehicle (by id, plate, owner, garage, rider); giving one to a garage; taking it out or back in; putting a player in it; locking, renaming, transferring; speed limit; repairing; health; upgrades; trunk; opening the menu.
api.garages()Reading garages; creating, deleting, renaming them, changing owner; members and roles with their permissions; checking a permission; opening the menu.
api.fuel()Fuel types, level and capacity, adding or setting fuel, creating and reading a jerrycan, list of pumps.
api.models()List and details of models (prices, speed, tank, hitbox, colors) and reloading the files.
api.shop()Models a player can buy, buying with payment through Vault, opening the shop.

Results and snapshots

  • Operations that change something return a value (ApiResult, PurchaseResult, UpgradeResult, RepairResult, EnterResult) instead of throwing exceptions: OK is the only success case. Always handle the default case too, since new values may appear.
  • Records like VehicleInfo, GarageInfo and ModelInfo are immutable snapshots: they do not update themselves, request the data again.

Rules to know

  • Main thread. Every method must be called from the server's main thread.
  • Permissions. Operations are "trusted", like a command run by an administrator: they do not check the garage's roles nor the ev.* permissions. The only exceptions are methods that act on behalf of a player who pays or gets on board (buy, repair(id, player), upgrade, enter), which respect that player's permissions.
  • Cancellable events. API calls also fire the cancellable events: another plugin can block them (CANCELLED result).
  • Version. EndlessVehiclesApi.API_VERSION only grows when the API changes; api.getApiVersion() tells you the installed plugin's version. A published version never changes.

Events

Events are plain Bukkit events, in the it.endlesshorizons.endlessvehicles.api.event package, synchronous and on the main thread. Listen with @EventHandler; the cancellable ones are blocked with setCancelled(true).

@EventHandler
public void onEnter(VehicleEnterEvent event) {
    var vehicle = EndlessVehiclesApi.get().vehicles().getVehicle(event.getVehicleId()).orElse(null);
    if (vehicle != null && vehicle.category() == VehicleCategory.EMERGENCY && !event.getPlayer().hasPermission("police.drive")) {
        event.setCancelled(true);
    }
}
EventWhen it firesCancellable
VehiclePreSpawnEventA player is about to take a vehicle out of the garageyes
VehicleSpawnedEventThe vehicle has appeared in the worldno
VehicleDespawnEventThe vehicle is about to be removed from the world (reason, and whether it is forced)yes (not if forced)
VehicleEnterEvent, VehicleLeaveEventA player gets in or out of a seatyes
VehicleClickEventA player right-clicks a vehicleyes
VehicleLockStateChangeEventA vehicle is about to be locked or unlockedyes
VehicleCollisionEventImpact against a block, a living entity or another vehicleyes (removes damage and knockback)
VehicleDestroyEventHealth reaches zeroyes (leaves 1 health)
VehicleRefuelEventFuel is about to be addedyes
VehicleUpgradeEventAn upgrade is about to be bought, before paymentyes
VehicleBuyEventA player is about to buy a vehicle, before paymentyes
VehicleGiveEventA vehicle is about to enter a garage (command, voucher, shop, transfer)yes
VehicleDeleteEventA vehicle is about to be deleted for goodyes
GarageOpenEventA garage's menu is about to openyes

The API's events fire before the plugin's own internal ones: if you cancel an API event, the operation stops.

For whoever publishes the module

The module is endlessvehicles-api (its own version, independent from the plugin). The instructions to build the Maven repository folder and upload it to the web server are in API-PUBLISHING.md at the project's root.