Skip to main content

Bukkit API

The Bukkit API is the foundational Minecraft server API that Paper builds upon. It provides comprehensive access to server functionality, game mechanics, and player interactions.

Core Classes

Server Access

org.bukkit.Bukkit

The main entry point for accessing server functionality:
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.entity.Player;

// Get the server instance
Server server = Bukkit.getServer();

// Get online players
Collection<? extends Player> players = Bukkit.getOnlinePlayers();

// Broadcast a message
Bukkit.broadcastMessage("Server announcement!");

// Get a world
World world = Bukkit.getWorld("world");

// Schedule a task
Bukkit.getScheduler().runTaskLater(plugin, () -> {
    // Code to run later
}, 20L); // 20 ticks = 1 second

org.bukkit.Server

Represents the server itself:
// Get server properties
String serverName = server.getName(); // "Paper"
String version = server.getVersion();
int maxPlayers = server.getMaxPlayers();

// World management
List<World> worlds = server.getWorlds();
World world = server.createWorld(new WorldCreator("custom_world"));

// Plugin access
PluginManager pm = server.getPluginManager();
Plugin myPlugin = pm.getPlugin("MyPlugin");

Player Management

org.bukkit.entity.Player

Represents a connected player:
// Player information
String name = player.getName();
UUID uuid = player.getUniqueId();
InetAddress address = player.getAddress().getAddress();

// Player state
GameMode gameMode = player.getGameMode();
boolean isOp = player.isOp();
Location location = player.getLocation();

// Player actions
player.teleport(location);
player.sendMessage("Hello!");
player.kick(Component.text("Goodbye!"));
player.setHealth(20.0);
player.setFoodLevel(20);

// Inventory access
PlayerInventory inventory = player.getInventory();
ItemStack item = inventory.getItemInMainHand();

World Management

org.bukkit.World

Represents a game world:
// World properties
String worldName = world.getName();
Environment env = world.getEnvironment(); // NORMAL, NETHER, THE_END
Difficulty difficulty = world.getDifficulty();

// Block access
Block block = world.getBlockAt(x, y, z);
block.setType(Material.STONE);

// Entity spawning
Entity entity = world.spawnEntity(location, EntityType.ZOMBIE);
Zombie zombie = (Zombie) entity;
zombie.setBaby(true);

// Chunk management
Chunk chunk = world.getChunkAt(x, z);
boolean loaded = chunk.isLoaded();
chunk.load();

// World settings
world.setDifficulty(Difficulty.HARD);
world.setStorm(true);
world.setTime(6000); // Noon

org.bukkit.Chunk

Represents a 16x16 chunk:
// Chunk coordinates
int x = chunk.getX();
int z = chunk.getZ();

// Chunk state
boolean loaded = chunk.isLoaded();
boolean forceLoaded = chunk.isForceLoaded();

// Load/unload
chunk.load(true);
chunk.unload();
chunk.setForceLoaded(true);

// Block access
for (BlockState state : chunk.getTileEntities()) {
    // Access tile entities
}

Commands

org.bukkit.command.Command

Base class for commands:
public class MyCommand extends Command {
    public MyCommand(String name) {
        super(name);
        setDescription("My custom command");
        setUsage("/mycommand <arg>");
        setPermission("myplugin.mycommand");
    }
    
    @Override
    public boolean execute(CommandSender sender, String label, String[] args) {
        if (args.length == 0) {
            sender.sendMessage("Usage: " + getUsage());
            return false;
        }
        
        // Command logic
        sender.sendMessage("Command executed!");
        return true;
    }
    
    @Override
    public List<String> tabComplete(CommandSender sender, String alias, String[] args) {
        if (args.length == 1) {
            return List.of("option1", "option2", "option3");
        }
        return List.of();
    }
}

org.bukkit.command.CommandSender

Represents any command executor:
// Send messages
sender.sendMessage("Message");
sender.sendMessage(Component.text("Fancy message"));

// Permission checks
if (sender.hasPermission("myplugin.admin")) {
    // Admin action
}

// Check if player
if (sender instanceof Player player) {
    // Player-specific actions
}

Configuration

org.bukkit.configuration.file.FileConfiguration

YAML configuration management:
FileConfiguration config = plugin.getConfig();

// Reading values
String message = config.getString("messages.welcome", "Welcome!");
int amount = config.getInt("amounts.default", 10);
boolean enabled = config.getBoolean("features.enabled", true);
List<String> list = config.getStringList("lists.items");

// Setting values
config.set("messages.goodbye", "Goodbye!");
config.set("amounts.max", 100);

// Save configuration
plugin.saveConfig();

// Reload configuration
plugin.reloadConfig();

// Configuration sections
ConfigurationSection section = config.getConfigurationSection("database");
String host = section.getString("host");
int port = section.getInt("port");

Scheduler

org.bukkit.scheduler.BukkitScheduler

Task scheduling and async operations:
BukkitScheduler scheduler = Bukkit.getScheduler();

// Synchronous tasks (on main thread)
scheduler.runTask(plugin, () -> {
    // Runs next tick
});

scheduler.runTaskLater(plugin, () -> {
    // Runs after delay
}, 20L); // 20 ticks = 1 second

scheduler.runTaskTimer(plugin, () -> {
    // Runs repeatedly
}, 0L, 20L); // Delay 0, repeat every 20 ticks

// Asynchronous tasks (off main thread)
scheduler.runTaskAsynchronously(plugin, () -> {
    // Database query, HTTP request, etc.
    // Cannot access Bukkit API from here!
});

scheduler.runTaskLaterAsynchronously(plugin, () -> {
    // Async task with delay
}, 20L);

scheduler.runTaskTimerAsynchronously(plugin, () -> {
    // Repeating async task
}, 0L, 100L);

// Cancel tasks
int taskId = scheduler.runTaskTimer(plugin, task, 0L, 20L);
scheduler.cancelTask(taskId);

// Cancel all plugin tasks
scheduler.cancelTasks(plugin);
Never access the Bukkit API from asynchronous tasks! Use runTask() to switch back to the main thread.

Inventory API

org.bukkit.inventory.Inventory

Inventory management:
// Create custom inventory
Inventory inv = Bukkit.createInventory(null, 27, Component.text("Custom GUI"));

// Add items
ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta meta = item.getItemMeta();
meta.displayName(Component.text("Legendary Sword"));
item.setItemMeta(meta);
inv.setItem(13, item);

// Open for player
player.openInventory(inv);

// Player inventory
PlayerInventory playerInv = player.getInventory();
ItemStack mainHand = playerInv.getItemInMainHand();
ItemStack offHand = playerInv.getItemInOffHand();
ItemStack helmet = playerInv.getHelmet();

Permissions

org.bukkit.permissions.Permission

Permission system:
// Check permissions
if (player.hasPermission("myplugin.use")) {
    // Allowed
}

if (player.isOp()) {
    // Is operator
}

// Permission objects
Permission perm = new Permission("myplugin.admin");
perm.setDescription("Allows admin access");
perm.setDefault(PermissionDefault.OP);

// Register permission
Bukkit.getPluginManager().addPermission(perm);

Utilities

Location

Location loc = new Location(world, x, y, z, yaw, pitch);
Location playerLoc = player.getLocation();

// Distance calculations
double distance = loc.distance(otherLoc);
double distanceSquared = loc.distanceSquared(otherLoc); // Faster

// Direction
Vector direction = loc.getDirection();

// Relative locations
Location above = loc.add(0, 1, 0);
Location inFront = loc.add(direction.multiply(5));

Material

Material type = Material.DIAMOND_SWORD;

boolean isBlock = type.isBlock();
boolean isItem = type.isItem();
boolean isSolid = type.isSolid();
boolean isTransparent = type.isTransparent();

Next Steps

Paper API

Explore Paper-specific enhancements

Events

Work with the event system

Adventure API

Modern text components

Plugin Development

Build your first plugin

Build docs developers (and LLMs) love