Skip to main content

Overview

The Ember Client Server API fires custom Bukkit events that you can listen to in your plugins. All events extend Bukkit’s PlayerEvent class.

Event Classes

EmberPlayerJoinEvent

Fired when a player joins the server using the Ember client.
public class EmberPlayerJoinEvent extends PlayerEvent

Constructor

public EmberPlayerJoinEvent(Player player)
player
Player
required
The player who joined using Ember client

Methods

getPlayer()
Returns the player who joined (inherited from PlayerEvent).
public Player getPlayer()
return
Player
The player who joined using the Ember client

Example

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

public class MyListener implements Listener {
    
    @EventHandler
    public void onEmberPlayerJoin(EmberPlayerJoinEvent event) {
        Player player = event.getPlayer();
        player.sendMessage("Welcome, Ember user!");
        
        // You can now safely send Ember-specific packets
    }
}
This event is fired after the player has been registered as an Ember client user. You can safely use ECServerAPI.sendPacket() for this player.

EmberAttestationRegisterEvent

Fired when the client responds to an attestation registration request.
public class EmberAttestationRegisterEvent extends PlayerEvent

Constructor

public EmberAttestationRegisterEvent(
    Player player,
    AttestationRegisterResult status,
    X509EncodedKeySpec publicKey
)
player
Player
required
The player who responded to the registration request
status
AttestationRegisterResult
required
The result of the registration attempt
publicKey
X509EncodedKeySpec
The client’s public key (only present if status is SUCCESS)

Methods

getPlayer()
public Player getPlayer()
return
Player
The player associated with this event
getStatus()
public AttestationRegisterResult getStatus()
return
AttestationRegisterResult
The result status of the registration attempt
Possible values:
  • SUCCESS - Registration completed successfully
  • SIGNING_NOT_ALLOWED - Client environment doesn’t support attestation
  • USER_CANCELLED - User cancelled the registration
  • UNKNOWN_ERROR - An unexpected error occurred
getPublicKey()
public X509EncodedKeySpec getPublicKey()
return
X509EncodedKeySpec
The client’s public key in X.509 format, or null if registration failed

Example

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

import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class AttestationListener implements Listener {
    
    private final Map<UUID, PublicKey> playerKeys = new HashMap<>();
    
    @EventHandler
    public void onAttestationRegister(EmberAttestationRegisterEvent event) {
        Player player = event.getPlayer();
        AttestationRegisterResult status = event.getStatus();
        
        if (status == AttestationRegisterResult.SUCCESS) {
            X509EncodedKeySpec keySpec = event.getPublicKey();
            
            try {
                // Convert to PublicKey object
                KeyFactory keyFactory = KeyFactory.getInstance("EC");
                PublicKey publicKey = keyFactory.generatePublic(keySpec);
                
                // Store for later use
                playerKeys.put(player.getUniqueId(), publicKey);
                
                player.sendMessage("Attestation key registered successfully!");
            } catch (Exception e) {
                player.sendMessage("Failed to process attestation key.");
                e.printStackTrace();
            }
        } else {
            player.sendMessage("Attestation registration failed: " + status);
        }
    }
}

EmberAttestationSignEvent

Fired when the client responds to an attestation signing request.
public class EmberAttestationSignEvent extends PlayerEvent

Constructor

public EmberAttestationSignEvent(
    Player player,
    AttestationSignResult status,
    byte[] signedData
)
player
Player
required
The player who responded to the signing request
status
AttestationSignResult
required
The result of the signing attempt
signedData
byte[]
The signed data (only present if status is SUCCESS)

Methods

getPlayer()
public Player getPlayer()
return
Player
The player associated with this event
getStatus()
public AttestationSignResult getStatus()
return
AttestationSignResult
The result status of the signing attempt
Possible values:
  • SUCCESS - Signing completed successfully
  • SIGNING_NOT_ALLOWED - Client environment doesn’t support attestation
  • SIGN_DATA_INVALID - The provided data was invalid
  • USER_CANCELLED - User cancelled the signing process
  • KEY_DOES_NOT_EXIST - No attestation key has been registered
  • UNKNOWN_ERROR - An unexpected error occurred
getSignedData()
public byte[] getSignedData()
return
byte[]
The cryptographically signed data, or null if signing failed

Example

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

import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.security.Signature;
import java.util.Map;
import java.util.UUID;

public class SignatureVerifier implements Listener {
    
    private final Map<UUID, PublicKey> playerKeys; // From registration
    private final byte[] challengeData = "verify_me".getBytes(StandardCharsets.UTF_8);
    
    public void requestSignature(Player player) {
        ECServerAPI api = ECServerAPI.getInstance();
        api.sendPacket(player, new OutAttestationSign(challengeData));
    }
    
    @EventHandler
    public void onAttestationSign(EmberAttestationSignEvent event) {
        Player player = event.getPlayer();
        AttestationSignResult status = event.getStatus();
        
        if (status == AttestationSignResult.SUCCESS) {
            byte[] signedData = event.getSignedData();
            PublicKey publicKey = playerKeys.get(player.getUniqueId());
            
            if (publicKey == null) {
                player.sendMessage("No public key found. Please register first.");
                return;
            }
            
            try {
                // Verify the signature
                Signature signature = Signature.getInstance("SHA256withECDSA");
                signature.initVerify(publicKey);
                signature.update(challengeData);
                
                if (signature.verify(signedData)) {
                    player.sendMessage("Signature verified! You are authenticated.");
                    // Grant access to protected features
                } else {
                    player.sendMessage("Signature verification failed!");
                    player.kickPlayer("Authentication failed");
                }
            } catch (Exception e) {
                player.sendMessage("Error verifying signature.");
                e.printStackTrace();
            }
        } else if (status == AttestationSignResult.KEY_DOES_NOT_EXIST) {
            player.sendMessage("Please register an attestation key first.");
        } else {
            player.sendMessage("Signing failed: " + status);
        }
    }
}

Complete Workflow Example

import com.emberclient.serverapi.ECServerAPI;
import com.emberclient.serverapi.event.EmberAttestationRegisterEvent;
import com.emberclient.serverapi.event.EmberAttestationSignEvent;
import com.emberclient.serverapi.event.EmberPlayerJoinEvent;
import com.emberclient.serverapi.packet.impl.attestation.register.AttestationRegisterResult;
import com.emberclient.serverapi.packet.impl.attestation.register.OutAttestationRegister;
import com.emberclient.serverapi.packet.impl.attestation.sign.AttestationSignResult;
import com.emberclient.serverapi.packet.impl.attestation.sign.OutAttestationSign;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class AttestationPlugin extends JavaPlugin implements Listener {
    
    private final Map<UUID, PublicKey> registeredKeys = new HashMap<>();
    private final byte[] CHALLENGE = "server_challenge".getBytes(StandardCharsets.UTF_8);
    
    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(this, this);
    }
    
    @EventHandler
    public void onEmberJoin(EmberPlayerJoinEvent event) {
        Player player = event.getPlayer();
        
        // Request attestation registration from Ember client
        ECServerAPI.getInstance().sendPacket(player, new OutAttestationRegister());
    }
    
    @EventHandler
    public void onRegister(EmberAttestationRegisterEvent event) {
        if (event.getStatus() == AttestationRegisterResult.SUCCESS) {
            Player player = event.getPlayer();
            
            try {
                // Store the public key
                KeyFactory kf = KeyFactory.getInstance("EC");
                PublicKey key = kf.generatePublic(event.getPublicKey());
                registeredKeys.put(player.getUniqueId(), key);
                
                // Request signature of challenge
                ECServerAPI.getInstance().sendPacket(player, new OutAttestationSign(CHALLENGE));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    @EventHandler
    public void onSign(EmberAttestationSignEvent event) {
        if (event.getStatus() == AttestationSignResult.SUCCESS) {
            Player player = event.getPlayer();
            PublicKey key = registeredKeys.get(player.getUniqueId());
            
            try {
                // Verify signature
                Signature sig = Signature.getInstance("SHA256withECDSA");
                sig.initVerify(key);
                sig.update(CHALLENGE);
                
                if (sig.verify(event.getSignedData())) {
                    player.sendMessage("You have been verified as an authentic Ember user!");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
Remember to register your event listener in your plugin’s onEnable() method:
getServer().getPluginManager().registerEvents(new MyListener(), this);

Build docs developers (and LLMs) love