Paper API
Paper extends the Bukkit API with numerous enhancements, optimizations, and new features. This page covers Paper-specific APIs in the io.papermc.paper and com.destroystokyo.paper packages.
Configuration API
Global Configuration
import io.papermc.paper.configuration.GlobalConfiguration;
// Access global configuration
GlobalConfiguration config = GlobalConfiguration.get();
// Chunk loading settings
int maxChunkSendRate = config.chunkLoading.playerMaxChunkSendRate;
int maxChunkLoadRate = config.chunkLoading.playerMaxChunkLoadRate;
// Proxy settings
boolean velocityEnabled = config.proxies.velocity.enabled;
String velocitySecret = config.proxies.velocity.secret;
// Console settings
boolean brigadierHighlighting = config.console.enableBrigadierHighlighting;
World Configuration
import io.papermc.paper.configuration.WorldConfiguration;
// Access per-world configuration
WorldConfiguration worldConfig = world.paperConfig();
// Entity spawn limits
int monsterLimit = worldConfig.spawnLimits.monster;
int animalLimit = worldConfig.spawnLimits.animal;
// Chunk system settings
int ioThreads = worldConfig.chunkSystem.ioThreads;
int workerThreads = worldConfig.chunkSystem.workerThreads;
// Anti-Xray
boolean antiXrayEnabled = worldConfig.anticheat.antiXray.enabled;
Registry API
Paper provides type-safe access to Minecraft registries:
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
// Access a registry
Registry<Enchantment> enchantments = RegistryAccess.registryAccess()
.getRegistry(RegistryKey.ENCHANTMENT);
// Get enchantment by key
Enchantment sharpness = enchantments.get(NamespacedKey.minecraft("sharpness"));
// Iterate all enchantments
for (Enchantment ench : enchantments) {
// Process enchantment
}
Registry Keys
Paper provides constants for registry keys:
import io.papermc.paper.registry.keys.EnchantmentKeys;
import io.papermc.paper.registry.keys.ItemTypeKeys;
import io.papermc.paper.registry.keys.BiomeKeys;
// Type-safe registry access
Enchantment sharpness = enchantments.get(EnchantmentKeys.SHARPNESS);
Material diamond = Registry.MATERIAL.get(ItemTypeKeys.DIAMOND);
Biome plains = Registry.BIOME.get(BiomeKeys.PLAINS);
Entity API
Entity AI
Customize mob AI behavior:
import com.destroystokyo.paper.entity.ai.Goal;
import com.destroystokyo.paper.entity.ai.GoalKey;
import com.destroystokyo.paper.entity.ai.GoalType;
import org.bukkit.entity.Mob;
Mob mob = (Mob) entity;
// Get AI goals
Set<Goal<?>> goals = mob.getGoals(GoalType.TARGET);
// Remove a goal
GoalKey<?> targetKey = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack"));
mob.removeGoal(targetKey);
// Add custom goal
Goal<Zombie> customGoal = /* custom implementation */;
mob.addGoal(customGoal, 5); // Priority 5
Entity Tracking
import io.papermc.paper.entity.TeleportFlag;
// Teleport with flags
entity.teleport(location,
TeleportFlag.EntityState.RETAIN_PASSENGERS,
TeleportFlag.EntityState.RETAIN_VEHICLE
);
// Get entity tracking range
int range = entity.getTrackedPlayers().size();
Datapack API
Manage datapacks at runtime:
import io.papermc.paper.datapack.Datapack;
import io.papermc.paper.datapack.DatapackManager;
DatapackManager manager = Bukkit.getDatapackManager();
// Get all datapacks
Collection<Datapack> packs = manager.getPacks();
// Get enabled datapacks
Collection<Datapack> enabled = manager.getEnabledPacks();
// Enable/disable datapack
Datapack pack = manager.getPack("my_datapack");
if (pack != null) {
pack.setEnabled(true);
}
// Refresh datapacks
manager.refreshPacks();
Chunk System
Chunk Scheduling
import io.papermc.paper.chunk.system.scheduling.ChunkLoadPriority;
// Set chunk priority
world.setChunkLoadPriority(chunkX, chunkZ, ChunkLoadPriority.URGENT);
// Get chunk status
Chunk.LoadLevel loadLevel = chunk.getLoadLevel();
boolean entityTicking = loadLevel.isEntityTicking();
Player API
Player Connection
// Get ping
int ping = player.getPing();
// Get client brand
String clientBrand = player.getClientBrandName();
// Kick with reason
player.kick(Component.text("Kicked for testing"),
PlayerKickEvent.Cause.PLUGIN);
Player Locale
import java.util.Locale;
// Get player locale
Locale locale = player.locale();
String language = locale.getLanguage(); // "en", "es", etc.
View Distance
// Per-player view distance
int viewDistance = player.getViewDistance();
player.setViewDistance(8);
// Simulation distance
int simDistance = player.getSimulationDistance();
player.setSimulationDistance(6);
Command API
Brigadier Integration
Paper exposes Brigadier for command handling:
import io.papermc.paper.command.brigadier.Commands;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
LifecycleEventManager<Plugin> manager = this.getLifecycleManager();
manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> {
Commands commands = event.registrar();
// Register Brigadier commands
});
}
}
Adventure API Integration
Paper fully integrates the Adventure API for modern text components. See Adventure API for details.
Timings
Paper provides advanced timing/profiling:
import co.aikar.timings.Timing;
import co.aikar.timings.Timings;
// Create timing
Timing timing = Timings.of(plugin, "My Operation");
// Time operation
timing.startTiming();
try {
// Code to time
} finally {
timing.stopTiming();
}
// Or use try-with-resources
try (Timing ignored = timing.startTiming()) {
// Code to time
}
Timings is being replaced by the Spark profiler in newer versions.
Profile API
Player profile management:
import com.destroystokyo.paper.profile.PlayerProfile;
import com.destroystokyo.paper.profile.ProfileProperty;
// Create profile
PlayerProfile profile = Bukkit.createProfile(uuid, "PlayerName");
// Get properties
Set<ProfileProperty> properties = profile.getProperties();
// Get textures
PlayerTextures textures = profile.getTextures();
URL skinUrl = textures.getSkin();
Ban API
Enhanced ban management:
import io.papermc.paper.ban.BanListType;
import org.bukkit.BanList;
// Get ban list
BanList<PlayerProfile> bans = Bukkit.getBanList(BanListType.PROFILE);
// Add ban
bans.addBan(profile, "Reason", expiration, "Moderator");
// Check if banned
boolean banned = bans.isBanned(profile);
Async Chunk API
Load chunks asynchronously:
import java.util.concurrent.CompletableFuture;
// Load chunk async
CompletableFuture<Chunk> future = world.getChunkAtAsync(x, z, true);
future.thenAccept(chunk -> {
// Chunk is loaded
});
// Load chunk async with generation
world.getChunkAtAsync(x, z, true, true).thenAccept(chunk -> {
// Chunk is loaded and generated if needed
});
Paper Events
Paper provides many additional events. See the Events API page for details.
Thread Safety
Most Paper API methods are not thread-safe and must be called from the main server thread. Use Bukkit.getScheduler().runTask() to switch to the main thread from async contexts.
// Async operation
CompletableFuture.supplyAsync(() -> {
// Database query, HTTP request, etc.
return result;
}).thenAccept(result -> {
// Switch to main thread for Bukkit API access
Bukkit.getScheduler().runTask(plugin, () -> {
player.sendMessage("Result: " + result);
});
});
Javadocs
Complete Paper API documentation:
papermc.io/javadocs
Next Steps
Events
Paper event system reference
Entities
Entity API and customization
World API
World manipulation