Public Bukkit API
Build server integrations on Nova’s normalized state.
Nova exposes a stable Java API for plugins running on the same Bukkit server. Read player and client state, inspect registered checks, query violations, use prediction context, control explicit exemptions, and integrate Nova Guard into competitive modes.
Reference reviewed on 12 August 2026.
Access
Accessing the Nova API
Nova owns the API instance. Never construct NovaAPI or
GuardAPI yourself. Use one of these supported access patterns after Nova
has enabled.
Direct plugin access
NovaAntiCheat nova = NovaAntiCheat.getInstance();
NovaAPI api = nova != null ? nova.getApi() : null;
Static helper
NovaAPI api = NovaAPI.get();
Bukkit services manager
RegisteredServiceProvider<NovaAPI> provider =
Bukkit.getServicesManager().getRegistration(NovaAPI.class);
NovaAPI api = provider != null ? provider.getProvider() : null;
A hard integration can declare depend: [NovaAntiCheat]. A plugin that can
operate without Nova may use softdepend: [NovaAntiCheat], look up the Bukkit
service, and handle a missing provider. No separate public API artifact or Maven
coordinate is promised currently.
Check api != null and api.isRunning() before relying on Nova. Cache neither internal Nova objects nor Guard runtime objects.
Core
Runtime and integration
isRunning()reports whether the Nova plugin instance is enabled.getVersion()returns Nova’s current version.reloadConfig()reloads Nova configuration;safeReload()runs Nova’s full safe reload flow.getDebugMode(player)returns that player’s current Nova debug mode.
Reload operations mutate live plugin state and must run on the Bukkit main thread.
Player state
Player and client state
These methods expose Nova’s server-side view without exposing prediction internals.
isPlayerTracked(player)reports whether Nova has created prediction state for the player.isPredictionReady(player)additionally requires that prediction is usable and movement is not currently blocked by a correction.isPredictionGrounded(player)— Nova’s current grounded result.isJavaPlayer(player),isBedrockPlayer(player),isEaglerPlayer(player), andgetEdition(player).getClientBrand(player),getClientVersion(player), andgetProtocolVersion(player). An unknown protocol returns-1.getPing(player),getAveragePing(player), andgetOnlinePlayerCount().
Edition booleans are mutually exclusive. Eagler sessions may still use compatible
Java-family detectors when Eagler checking is enabled, so use getEdition(player)
when the exact client family matters.
if (api.isPlayerTracked(player) && api.isPredictionReady(player)) {
String edition = api.getEdition(player);
String version = api.getClientVersion(player);
int ping = api.getPing(player);
}
Check catalog
Checks and metadata
Prefer qualified check IDs such as java:Speed-A. Qualification prevents a
Java, Bedrock, prediction, or Guard check with a similar display name from being
confused with another check.
getRegisteredChecks()returns registered qualified IDs.getChecks()andgetCheck("java:Speed-A")returnCheckDetails.isCheckEnabled(id),isCheckRegistered(id),getCheckCategory(id), andgetCheckDisplayName(id).
CheckDetails provides getQualifiedId(), getId(),
getDisplayName(), getCategory(), getEdition(),
getClientSupport(), isExperimental(),
isEnabled(), and getConfigPath().
for (NovaAPI.CheckDetails check : api.getChecks()) {
getLogger().info(check.getQualifiedId()
+ " | " + check.getCategory()
+ " | " + check.getClientSupport());
}
Violations
Read and reset violation state
getViolations(player, "java:Speed-A")reads one check’s current VL.getTotalViolations(player)reads the player’s aggregate tracked VL.hasFlaggedRecently(player, "java:Speed-A", 20)checks a recent tick window.resetViolations(player, "java:Speed-A")andresetAllViolations(player)mutate tracked violation state.
A value of 20 means approximately one second at normal server tick rate, not 20 milliseconds.
Responses
Exemptions and setbacks
These calls change Nova behavior and should be reserved for deliberate server logic.
hasBypass(player, "java:Speed-A")checks the configured bypass permission.grantTemporaryExemption(player, 40),grantPermanentExemption(player), andrevokeTemporaryExemption(player).isTemporarilyExempt(player)andgetTemporaryExemptionTicksRemaining(player).isSetbacked(player),getSetbackTicksRemaining(player), andforceSetback(player).
Do not grant an exemption merely because a player uses Nova Guard. Guard verification is additional evidence and never a trust bonus.
Context
Movement and context helpers
isInLiquid(player),isInWeb(player),isClimbing(player),isOnIce(player), andisOnSlime(player).hasRecentTeleport(player, 20),hasRecentVelocity(player, 20), andhasRecentDamage(player, 20).hasRecentRodPull(player, 8),hasRecentWind(player, 20), andhasRecentSpearJab(player, 20).
All withinTicks arguments are Minecraft tick windows. These helpers reuse Nova’s normalized state instead of requiring an integration to reproduce environment tracking.
AntiESP
Visibility integration
isHiddenFrom(viewer, target)reports Nova’s current visibility decision.refreshViewerVisibility(viewer)refreshes one viewer.refreshAllViewerVisibility()refreshes all viewers.getAntiEspPerformanceStats()returns a concise diagnostic summary.
Nova Pro and Dev
Nova Guard API
Access Guard through api.getGuardApi() or
nova.getGuardApi(). Nova also provides flat convenience methods for the
common operations. Guard is available with Nova Pro and Dev entitlements. On an
unavailable or non-Pro installation, the API returns conservative inactive results.
isGuardEnabled(),isGuardVerified(player), andgetGuardStatus(player).getGuardRequirement()returns the global policy;getGuardRequirementInfo(player)returns the effective player policy and safe label.getGuardSessionExpiry(player)andisGuardRequired(player).requireGuard(player, "Ranked Queue")andclearGuardRequirement(player).getGuardSessions()returns privacy-safe snapshots of current local-backend paired sessions.
Player and UUID overloads exist for state, expiry, requirement, require, and clear operations. A per-player requirement is removed when the player disconnects. Clearing it only removes the API-created requirement: a global REQUIRED policy cannot be cleared or bypassed by another plugin.
A Guard requirement failure is session/access policy, not a cheating violation. Verified Guard does not lower VL, reduce confidence, disable checks, weaken normal Nova, or make setbacks less strict.
Stable state model
Guard statuses and results
| GuardStatus | Meaning |
|---|---|
DISABLED | Guard is inactive or unavailable for this installation/player. |
UNPAIRED | No current paired Guard launch is available. |
PAIRING | Pairing or connection establishment is in progress. |
VERIFIED | Guard is active and eligible as an additional verified source. |
PAUSED | Verification is temporarily unavailable; do not treat this as a cheat result. |
DISCONNECTED | The Guard connection or Minecraft session was lost. |
EXPIRED | The current Guard launch session expired. |
GuardRequirement is DISABLED, OPTIONAL, or REQUIRED.
GuardRequirementInfo provides getRequirement(),
getReason(), isGlobal(), isRequired(), and
getDisplayName().
Successful GuardRequirementResult values are APPLIED,
UPDATED, and ALREADY_REQUIRED. Failure values are
GUARD_UNAVAILABLE, PLAYER_OFFLINE,
PLAYER_NOT_APPLICABLE, PLAYER_BYPASSED,
INVALID_REASON, and NOT_SERVER_THREAD. Check
result.isSuccessful() rather than assuming every call applied.
GuardSessionInfo is a privacy-safe session snapshot with
getPlayerId(), getPlayerName(), getStatus(),
getRequirement(), and getSessionExpiry().
Events
Guard events
All public Guard events are synchronous Bukkit events fired on the Bukkit server thread.
GuardStatusChangeEventexposesgetPreviousStatus()andgetNewStatus().GuardVerifiedEventfires when active, correlation-eligible verification is gained.GuardVerificationLostEventfires when a previously verified player loses active verification and exposesgetNewStatus().
Common getters are getPlayer(), getPlayerId(),
getRequirement(), getReason(), and
getSessionExpiry(). The optional reason is diagnostic context; do not
display it directly to players or branch on exact strings.
@EventHandler
public void onGuardStatusChange(GuardStatusChangeEvent event) {
switch (event.getNewStatus()) {
case VERIFIED -> updateCompetitiveAccess(event.getPlayer(), true);
case PAUSED, DISCONNECTED, EXPIRED ->
updateCompetitiveAccess(event.getPlayer(), false);
default -> { }
}
}
Example
Require Guard for a ranked queue
Keep the server globally OPTIONAL, require Guard only when a player enters competitive matchmaking, and wait for verification before admitting them.
private GuardAPI guardApi() {
NovaAPI api = NovaAPI.get();
return api != null ? api.getGuardApi() : null;
}
public void requestRankedAccess(Player player) {
GuardAPI guard = guardApi();
if (guard == null || !guard.isGuardEnabled()) {
denyRanked(player, "Nova Guard is unavailable.");
return;
}
if (guard.isGuardVerified(player)) {
enterRankedMode(player);
return;
}
GuardRequirementResult result =
guard.requireGuard(player, "Ranked Queue");
if (!result.isSuccessful()) {
denyRanked(player, "Guard could not be required: " + result);
}
}
@EventHandler
public void onGuardVerified(GuardVerifiedEvent event) {
if (rankedQueue.contains(event.getPlayerId())) {
enterRankedMode(event.getPlayer());
}
}
@EventHandler
public void onGuardLost(GuardVerificationLostEvent event) {
if (rankedMatch.contains(event.getPlayerId())) {
pauseCompetitiveAccess(event.getPlayer(), event.getNewStatus());
}
}
public void leaveRanked(Player player) {
GuardAPI guard = guardApi();
if (guard != null) {
guard.clearGuardRequirement(player);
}
}
The player receives Nova’s normal Guard grace and pairing flow. Grace expiry follows the Guard access policy without cheat VL. Normal Nova checks remain fully active for verified and unverified players.
Optional integration
PlaceholderAPI
PlaceholderAPI is an optional soft dependency. Nova works normally without it.
| Placeholder | Example |
|---|---|
%nova_version% | Current Nova version |
%nova_status% | Active |
%nova_tps% | 19.98 |
%nova_client_edition% | Java, Bedrock, or Eagler |
%nova_client_version% | 1.21.11 |
%nova_checks_enabled% | true |
%nova_ping% | 42 |
%nova_average_ping% | 47 |
%nova_guard_status% | VERIFIED |
%nova_guard_verified% | true |
%nova_guard_requirement% | OPTIONAL, REQUIRED, or a safe per-player label |
%nova_guard_session_remaining% | 21h 42m |
When Guard is unavailable, Guard placeholders return safe inactive values such as DISABLED, false, and N/A.
Contract
Threading, lifecycle and safety
- Call Guard requirement mutations,
reloadConfig(), andsafeReload()on the Bukkit main thread. - Guard events already run synchronously on the Bukkit server thread.
- Use concise, nonblank per-player requirement labels because they may appear in administrator views and placeholders.
- Prefer query methods for display logic. Treat resets, exemptions, setbacks, reloads, and requirements as intentional mutations.
- Handle disabled, unavailable, offline, unknown, and empty optional results rather than assuming every player has complete state.
It does not expose session keys, raw input, telemetry, IP addresses, authentication secrets, transport state, or Guard protocol internals.
The supported public boundary is me.cerial.NovaAntiCheat.api, including
api.guard and api.guard.event. Packages under Nova’s
utils tree, NovaGuardProtocol, and NovaGuardVelocity are internal and may
change without API compatibility guarantees.