Installation
The SDK is one Java class with no dependencies. You shade it into your plugin's jar and move it into your own package.
Coordinates
| Repository | https://pluginanalytics.dev/maven |
|---|---|
| Group | com.gamepathics |
| Artifact | pluginanalytics-bukkit |
| Version | 1.2.0 |
| Package to relocate | com.gamepathics.pluginanalytics |
The artifact also publishes sources and javadoc jars, so your IDE shows the documentation of every method.
Gradle (Kotlin DSL)
// build.gradle.kts
plugins {
java
id("com.gradleup.shadow") version "8.3.9"
}
repositories {
mavenCentral()
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://pluginanalytics.dev/maven")
}
dependencies {
compileOnly("org.spigotmc:spigot-api:1.21.1-R0.1-SNAPSHOT")
implementation("com.gamepathics:pluginanalytics-bukkit:1.2.0")
}
tasks.shadowJar {
archiveClassifier.set("")
relocate("com.gamepathics.pluginanalytics", "me.you.arenaplus.libs.analytics")
}
tasks.build {
dependsOn(tasks.shadowJar)
}
Gradle (Groovy DSL)
// build.gradle
plugins {
id 'java'
id 'com.gradleup.shadow' version '8.3.9'
}
repositories {
mavenCentral()
maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
maven { url = 'https://pluginanalytics.dev/maven' }
}
dependencies {
compileOnly 'org.spigotmc:spigot-api:1.21.1-R0.1-SNAPSHOT'
implementation 'com.gamepathics:pluginanalytics-bukkit:1.2.0'
}
shadowJar {
archiveClassifier.set('')
relocate 'com.gamepathics.pluginanalytics', 'me.you.arenaplus.libs.analytics'
}
build.dependsOn shadowJar
Build with ./gradlew build (or shadowJar) and put the jar from build/libs on your server. The plain jar task doesn't include the SDK.
Maven
A complete pom.xml: the repository, the dependency, and maven-shade-plugin with the relocation.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.you</groupId>
<artifactId>arenaplus</artifactId>
<version>1.4.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>pluginanalytics</id>
<url>https://pluginanalytics.dev/maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.21.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.gamepathics</groupId>
<artifactId>pluginanalytics-bukkit</artifactId>
<version>1.2.0</version>
<!-- compile scope (the default): it goes inside your jar -->
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>com.gamepathics.pluginanalytics</pattern>
<shadedPattern>me.you.arenaplus.libs.analytics</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Build with mvn package. The jar in target/ contains your plugin and the relocated SDK.
Why relocation is required
Many plugins on one server can use PluginAnalytics, each with its own copy, possibly of different versions. Bukkit lets plugins see each other's classes, so two jars that both contain com.gamepathics.pluginanalytics.PluginAnalytics could end up sharing one copy: the wrong version, or another plugin's settings. Moving the SDK into your own package makes your copy yours alone.
The SDK checks this when it starts: it compares the package of its own class with the original one (built at runtime, so the shading tool can't rewrite the comparison). If it wasn't relocated, it turns itself off and your plugin keeps working:
[ArenaPlus] PluginAnalytics is disabled: relocate com.gamepathics.pluginanalytics into your plugin's package.
To check a build, list the jar: you should see the class under your package and nothing under com/gamepathics.
unzip -l build/libs/ArenaPlus.jar | grep PluginAnalytics
# me/you/arenaplus/libs/analytics/PluginAnalytics.class
# me/you/arenaplus/libs/analytics/PluginAnalytics$Span.class
# ...
Relocating into a sub-package of your plugin (like me.you.arenaplus.libs.analytics) is the convention. The performance sampler leaves the SDK's own classes out either way.
Java and server versions
- The SDK is compiled for Java 8 against the Bukkit 1.8.8 API, so it runs inside plugins built for any Java version from 8 up, on 1.8 through the latest releases.
- It runs on Bukkit, Spigot, Paper, Purpur and Folia, and reports which one each server uses.
- It has no dependencies. On servers that use log4j (Spigot and Paper), it reads errors from log4j too, through reflection.
plugin.yml and paper-plugin.yml
- Nothing to add: there's no PluginAnalytics plugin to depend on. The SDK lives in your jar.
- Commands are counted and timed automatically when they're declared in
plugin.ymland run through your executor. Commands you register another way (for example through Paper's Brigadier lifecycle API in apaper-plugin.ymlplugin) aren't wrapped: track them yourself. - Your
dependandsoftdependlists are read to report which of those plugins each server has installed. - The
versionin your plugin.yml is the version shown everywhere in the dashboard and compared for update notices, so keep it in a numeric form like1.4.0.
Folia
The SDK detects Folia and skips everything that needs a single main thread. On Folia:
| Works | Doesn't run |
|---|---|
Servers, players, versions, retention · track events and properties · player first joins and funnels · config usage · errors and logs · spans (time) · update notices and feedback |
Main-thread sampling · automatic timing of event handlers and commands · automatic command events (they come from the same command wrapper) · server tick time (MSPT) |
Declare folia-supported: true in your plugin.yml as usual if your plugin supports Folia; the SDK doesn't need anything else. Property suppliers run on the SDK's own thread, so on Folia only read values that don't belong to a region.