Skip to main content
This guide will walk you through the essential features of the Server API using real code examples.

Get the API Instance

The ECServerAPI class is the main entry point for all API functionality. Access it using the singleton pattern:
import com.emberclient.serverapi.ECServerAPI;

ECServerAPI api = ECServerAPI.getInstance();
The API instance is available after the ECServerAPI plugin loads. If you declared it as a softdepend in your plugin.yml, it will be available in your onEnable() method.

Check if a Player is Using Ember Client

Before sending packets or using Ember-specific features, verify that the player is using Ember Client:
import org.bukkit.entity.Player;
import java.util.UUID;

Player player = // ... get player
UUID uuid = player.getUniqueId();

if (api.isPlayerOnEmber(uuid)) {
    player.sendMessage("Welcome, Ember Client user!");
} else {
    player.sendMessage("You're using vanilla Minecraft.");
}
The isPlayerOnEmber() method is automatically updated when players join or leave, and when they register/unregister the plugin channel.

Send a Packet to the Client

Send custom packets to Ember Client users. Here’s an example using the attestation register packet:
import com.emberclient.serverapi.packet.impl.attestation.register.OutAttestationRegister;

Player player = // ... get player

// Only send to Ember Client users
if (api.isPlayerOnEmber(player.getUniqueId())) {
    OutAttestationRegister packet = new OutAttestationRegister();
    api.sendPacket(player, packet);
}
import com.emberclient.serverapi.ECServerAPI;
import com.emberclient.serverapi.packet.impl.attestation.register.OutAttestationRegister;
import org.bukkit.entity.Player;

public void requestAttestation(Player player) {
    ECServerAPI api = ECServerAPI.getInstance();
    
    if (!api.isPlayerOnEmber(player.getUniqueId())) {
        player.sendMessage("You must use Ember Client for this feature.");
        return;
    }
    
    OutAttestationRegister packet = new OutAttestationRegister();
    api.sendPacket(player, packet);
    player.sendMessage("Please complete the attestation on your device.");
}
The sendPacket() method automatically checks if the player is using Ember Client and silently returns if they’re not. Always verify beforehand if you need to provide user feedback.

Listen to Events

The API fires Bukkit events that you can listen to. Here are the most common events:

Detect When a Player Joins with Ember Client

import com.emberclient.serverapi.event.EmberPlayerJoinEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class EmberListener implements Listener {
    
    @EventHandler
    public void onEmberPlayerJoin(EmberPlayerJoinEvent event) {
        Player player = event.getPlayer();
        player.sendMessage("Ember Client detected! Special features enabled.");
        
        // Grant permissions, show custom UI, etc.
    }
}

Handle Attestation Registration

import com.emberclient.serverapi.event.EmberAttestationRegisterEvent;
import com.emberclient.serverapi.packet.impl.attestation.register.AttestationRegisterResult;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

import java.security.spec.X509EncodedKeySpec;

public class AttestationListener implements Listener {
    
    @EventHandler
    public void onAttestationRegister(EmberAttestationRegisterEvent event) {
        Player player = event.getPlayer();
        AttestationRegisterResult status = event.getStatus();
        X509EncodedKeySpec publicKey = event.getPublicKey();
        
        if (status == AttestationRegisterResult.SUCCESS) {
            // Store the public key for this player
            // You can now use it for signature verification
            player.sendMessage("2FA setup complete!");
        } else {
            player.sendMessage("2FA setup failed. Please try again.");
        }
    }
}

Handle Attestation Signatures

import com.emberclient.serverapi.event.EmberAttestationSignEvent;
import com.emberclient.serverapi.packet.impl.attestation.sign.AttestationSignResult;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class SignatureListener implements Listener {
    
    @EventHandler
    public void onAttestationSign(EmberAttestationSignEvent event) {
        Player player = event.getPlayer();
        AttestationSignResult status = event.getStatus();
        byte[] signedData = event.getSignedData();
        
        if (status == AttestationSignResult.SUCCESS) {
            // Verify the signature using stored public key
            // Grant access to protected resources
            player.sendMessage("Authentication successful!");
        } else {
            player.sendMessage("Authentication failed.");
        }
    }
}

Register Your Event Listener

Don’t forget to register your listener in your plugin’s onEnable() method:
public class YourPlugin extends JavaPlugin {
    
    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(new EmberListener(), this);
        getServer().getPluginManager().registerEvents(new AttestationListener(), this);
        getServer().getPluginManager().registerEvents(new SignatureListener(), this);
    }
}

Complete Example

Here’s a complete example that ties everything together:
import com.emberclient.serverapi.ECServerAPI;
import com.emberclient.serverapi.event.EmberPlayerJoinEvent;
import com.emberclient.serverapi.event.EmberAttestationRegisterEvent;
import com.emberclient.serverapi.packet.impl.attestation.register.OutAttestationRegister;
import com.emberclient.serverapi.packet.impl.attestation.register.AttestationRegisterResult;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;

public class EmberIntegration extends JavaPlugin implements Listener {
    
    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(this, this);
    }
    
    @EventHandler
    public void onEmberJoin(EmberPlayerJoinEvent event) {
        Player player = event.getPlayer();
        player.sendMessage("Welcome! Type /setup2fa to enable two-factor authentication.");
    }
    
    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("This command is for players only.");
            return true;
        }
        
        Player player = (Player) sender;
        ECServerAPI api = ECServerAPI.getInstance();
        
        if (command.getName().equalsIgnoreCase("setup2fa")) {
            if (!api.isPlayerOnEmber(player.getUniqueId())) {
                player.sendMessage("You must use Ember Client for 2FA.");
                return true;
            }
            
            OutAttestationRegister packet = new OutAttestationRegister();
            api.sendPacket(player, packet);
            player.sendMessage("Please complete 2FA setup on your device.");
            return true;
        }
        
        return false;
    }
    
    @EventHandler
    public void onRegister(EmberAttestationRegisterEvent event) {
        Player player = event.getPlayer();
        
        if (event.getStatus() == AttestationRegisterResult.SUCCESS) {
            // In production, store event.getPublicKey() in your database
            player.sendMessage("2FA enabled! Your account is now protected.");
        }
    }
}

Next Steps

Core Concepts

Deep dive into packets, events, and the API architecture

Attestation Guide

Build a complete 2FA system with attestation

Build docs developers (and LLMs) love