Player events track individual player actions and settings within the SuperiorSkyblock2 plugin, independent of specific island actions.
Role Management
PlayerChangeRoleEvent
Called when a player’s island role changes.
import com.bgsoftware.superiorskyblock.api.events.PlayerChangeRoleEvent;
import com.bgsoftware.superiorskyblock.api.island.PlayerRole;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class RoleListener implements Listener {
@EventHandler
public void onRoleChange(PlayerChangeRoleEvent event) {
SuperiorPlayer player = event.getPlayer();
PlayerRole newRole = event.getNewRole();
PlayerRole oldRole = player.getPlayerRole();
// Prevent demoting from specific role
if (oldRole.getWeight() > newRole.getWeight() &&
oldRole.toString().equals("Moderator")) {
event.setCancelled(true);
return;
}
// Notify player of promotion
if (newRole.getWeight() > oldRole.getWeight()) {
player.asPlayer().sendMessage(
"Congratulations! You've been promoted to " + newRole.toString()
);
}
// Grant permissions based on role
grantRolePermissions(player, newRole);
}
}
Event Properties:
getPlayer() - The player whose role is changing
getNewRole() - The new role being assigned
isCancelled() / setCancelled(boolean) - Cancel the role change
The player’s current role can be obtained via player.getPlayerRole() before the event completes. Compare weights to determine if it’s a promotion or demotion.
Player Settings
PlayerChangeBorderColorEvent
Called when a player changes their world border color.
@EventHandler
public void onBorderColorChange(PlayerChangeBorderColorEvent event) {
SuperiorPlayer player = event.getPlayer();
BorderColor borderColor = event.getBorderColor();
// Restrict certain colors to VIP
if (borderColor == BorderColor.GOLD &&
!player.asPlayer().hasPermission("vip.border.gold")) {
event.setCancelled(true);
player.asPlayer().sendMessage("Gold border color is VIP only!");
return;
}
player.asPlayer().sendMessage(
"Border color changed to " + borderColor.name()
);
}
PlayerChangeLanguageEvent
Called when a player changes their language preference.
@EventHandler
public void onLanguageChange(PlayerChangeLanguageEvent event) {
SuperiorPlayer player = event.getPlayer();
Locale language = event.getLanguage();
plugin.getLogger().info(
player.getName() + " changed language to " + language.getDisplayName()
);
// Send confirmation in new language
String message = getLocalizedMessage("language.changed", language);
player.asPlayer().sendMessage(message);
}
PlayerChangeNameEvent
Called when a player’s display name changes (not Minecraft username).
@EventHandler
public void onNameChange(PlayerChangeNameEvent event) {
SuperiorPlayer player = event.getPlayer();
String newName = event.getNewName();
// Validate name format
if (!newName.matches("^[a-zA-Z0-9_]{3,16}$")) {
event.setCancelled(true);
player.asPlayer().sendMessage("Invalid name format!");
return;
}
// Check for duplicate names
if (isNameTaken(newName)) {
event.setCancelled(true);
player.asPlayer().sendMessage("That name is already taken!");
}
}
Toggle Events
These events are triggered when players toggle various features on or off.
PlayerToggleBorderEvent
Called when a player toggles their world border visibility.
@EventHandler
public void onToggleBorder(PlayerToggleBorderEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
if (enabled) {
player.asPlayer().sendMessage("World border enabled");
} else {
player.asPlayer().sendMessage("World border disabled");
}
}
PlayerToggleFlyEvent
Called when a player toggles island fly mode.
@EventHandler
public void onToggleFly(PlayerToggleFlyEvent event) {
SuperiorPlayer player = event.getPlayer();
Island island = event.getIsland();
boolean enabled = event.isEnabled();
// Require permission for fly
if (enabled && !player.hasPermission("island.fly")) {
event.setCancelled(true);
player.asPlayer().sendMessage("You don't have permission to fly!");
return;
}
// Charge for fly activation
if (enabled && !player.asPlayer().hasPermission("vip.fly.free")) {
if (!chargeFlyFee(player, 100)) {
event.setCancelled(true);
player.asPlayer().sendMessage("Insufficient funds for fly mode!");
}
}
}
PlayerToggleFlyEvent is specific to island fly mode, not general Minecraft flight. It only affects flight within the player’s island boundaries.
PlayerToggleBypassEvent
Called when a player toggles island protection bypass mode.
@EventHandler
public void onToggleBypass(PlayerToggleBypassEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
// Require admin permission
if (!player.asPlayer().hasPermission("superiorskyblock.bypass")) {
event.setCancelled(true);
return;
}
// Log bypass usage
plugin.getLogger().warning(
player.getName() + (enabled ? " enabled" : " disabled") + " bypass mode"
);
}
PlayerTogglePanelEvent
Called when a player toggles the top panel display.
@EventHandler
public void onTogglePanel(PlayerTogglePanelEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
// Save preference
playerData.setPanelEnabled(player.getUniqueId(), enabled);
}
PlayerToggleTeamChatEvent
Called when a player toggles island team chat.
@EventHandler
public void onToggleTeamChat(PlayerToggleTeamChatEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
if (enabled) {
player.asPlayer().sendMessage("Team chat enabled - messages will be sent to island members only");
} else {
player.asPlayer().sendMessage("Team chat disabled - messages will be sent globally");
}
}
PlayerToggleSpyEvent
Called when a player toggles spy mode to see island team chats.
@EventHandler
public void onToggleSpy(PlayerToggleSpyEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
// Require admin permission
if (!player.asPlayer().hasPermission("superiorskyblock.spy")) {
event.setCancelled(true);
return;
}
// Log spy activation
if (enabled) {
plugin.getLogger().info(player.getName() + " enabled spy mode");
spyModeUsers.add(player.getUniqueId());
} else {
spyModeUsers.remove(player.getUniqueId());
}
}
PlayerToggleBlocksStackerEvent
Called when a player toggles the block stacker feature.
@EventHandler
public void onToggleBlocksStacker(PlayerToggleBlocksStackerEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
if (enabled) {
player.asPlayer().sendMessage("Block stacker enabled - blocks will stack automatically");
} else {
player.asPlayer().sendMessage("Block stacker disabled");
}
}
Called when a player opens a SuperiorSkyblock2 menu.
@EventHandler
public void onMenuOpen(PlayerOpenMenuEvent event) {
SuperiorPlayer player = event.getPlayer();
MenuView menuView = event.getMenuView();
String menuIdentifier = menuView.getIdentifier();
// Track menu usage
trackMenuOpen(player, menuIdentifier);
// Prevent opening certain menus
if (menuIdentifier.equals("top-islands") && !player.hasPermission("menu.top")) {
event.setCancelled(true);
player.asPlayer().sendMessage("You don't have permission to view this menu!");
}
}
Called when a player closes a SuperiorSkyblock2 menu.
@EventHandler
public void onMenuClose(PlayerCloseMenuEvent event) {
SuperiorPlayer player = event.getPlayer();
MenuView menuView = event.getMenuView();
// Save any pending changes
if (menuView.getIdentifier().equals("island-settings")) {
savePendingSettings(player);
}
}
Menu events allow you to track player navigation through the plugin’s GUI system and implement custom validation or side effects.
Player Replacement
PlayerReplaceEvent
Called when a player object is being replaced (usually due to a nickname change or data refresh).
@EventHandler
public void onPlayerReplace(PlayerReplaceEvent event) {
SuperiorPlayer oldPlayer = event.getOldPlayer();
SuperiorPlayer newPlayer = event.getNewPlayer();
// Transfer custom data
transferCustomData(oldPlayer, newPlayer);
// Update references
updatePlayerReferences(oldPlayer.getUniqueId(), newPlayer);
}
This is an advanced event typically used by other plugins that maintain player data. Most developers won’t need to handle this event.
Message Events
AttemptPlayerSendMessageEvent
Called before a message is sent to a player by the plugin.
@EventHandler
public void onAttemptSendMessage(AttemptPlayerSendMessageEvent event) {
SuperiorPlayer player = event.getPlayer();
String message = event.getMessage();
// Filter messages for muted players
if (isMuted(player)) {
event.setCancelled(true);
return;
}
// Custom message formatting
String formatted = applyCustomFormatting(message, player);
event.setMessage(formatted);
}
SendMessageEvent
Called when a message is being sent to a player.
@EventHandler
public void onSendMessage(SendMessageEvent event) {
String message = event.getMessage();
// Log important messages
if (message.contains("island") || message.contains("upgrade")) {
plugin.getLogger().info("Message sent: " + message);
}
}
Complete Event Examples
VIP Features Manager
public class VIPFeaturesListener implements Listener {
@EventHandler
public void onToggleFly(PlayerToggleFlyEvent event) {
SuperiorPlayer player = event.getPlayer();
if (!event.isEnabled()) return;
// VIPs fly for free, others pay
if (player.asPlayer().hasPermission("vip.fly")) {
player.asPlayer().sendMessage("VIP fly activated!");
} else if (withdraw(player, 100)) {
player.asPlayer().sendMessage("Fly activated for $100");
} else {
event.setCancelled(true);
player.asPlayer().sendMessage("Insufficient funds! Fly costs $100");
}
}
@EventHandler
public void onBorderColorChange(PlayerChangeBorderColorEvent event) {
SuperiorPlayer player = event.getPlayer();
BorderColor color = event.getBorderColor();
// Premium colors for VIP
List<BorderColor> vipColors = Arrays.asList(
BorderColor.GOLD, BorderColor.AQUA, BorderColor.LIGHT_PURPLE
);
if (vipColors.contains(color) && !player.asPlayer().hasPermission("vip.border")) {
event.setCancelled(true);
player.asPlayer().sendMessage("This border color is VIP only!");
}
}
}
public class RolePromotionListener implements Listener {
@EventHandler
public void onRoleChange(PlayerChangeRoleEvent event) {
SuperiorPlayer player = event.getPlayer();
PlayerRole newRole = event.getNewRole();
PlayerRole oldRole = player.getPlayerRole();
Island island = player.getIsland();
if (island == null) return;
// Promotion
if (newRole.getWeight() > oldRole.getWeight()) {
// Celebrate promotion
island.sendMessage(
"§6" + player.getName() + " has been promoted to " +
newRole.toString() + "!"
);
// Grant promotion rewards
givePromotionReward(player, newRole);
// Achievement tracking
incrementAchievement(player, "promotions_received");
}
// Demotion
else if (newRole.getWeight() < oldRole.getWeight()) {
// Prevent demoting the last admin
if (oldRole.toString().equals("Admin") &&
getAdminCount(island) <= 1) {
event.setCancelled(true);
player.asPlayer().sendMessage(
"Cannot demote the last admin!"
);
}
}
}
private int getAdminCount(Island island) {
return (int) island.getIslandMembers(false).stream()
.filter(member -> member.getPlayerRole().toString().equals("Admin"))
.count();
}
}
Player Preferences Manager
public class PreferencesListener implements Listener {
@EventHandler
public void onLanguageChange(PlayerChangeLanguageEvent event) {
SuperiorPlayer player = event.getPlayer();
Locale language = event.getLanguage();
// Save to database
database.saveLanguage(player.getUniqueId(), language);
// Update scoreboard in new language
updateScoreboard(player, language);
// Send confirmation
player.asPlayer().sendMessage(
translate("language.changed", language)
);
}
@EventHandler
public void onTogglePanel(PlayerTogglePanelEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
// Save preference
database.savePanelPreference(player.getUniqueId(), enabled);
// Apply immediately
if (enabled) {
showPanel(player);
} else {
hidePanel(player);
}
}
@EventHandler
public void onToggleBorder(PlayerToggleBorderEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
database.saveBorderPreference(player.getUniqueId(), enabled);
if (enabled) {
showBorder(player);
} else {
hideBorder(player);
}
}
}
public class AdminToolsListener implements Listener {
@EventHandler
public void onToggleBypass(PlayerToggleBypassEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
if (!player.asPlayer().hasPermission("superiorskyblock.bypass")) {
event.setCancelled(true);
return;
}
// Log bypass usage
String action = enabled ? "enabled" : "disabled";
plugin.getLogger().warning(
"[ADMIN] " + player.getName() + " " + action + " bypass mode"
);
// Notify other admins
notifyAdmins(player.getName() + " " + action + " bypass mode");
}
@EventHandler
public void onToggleSpy(PlayerToggleSpyEvent event) {
SuperiorPlayer player = event.getPlayer();
boolean enabled = event.isEnabled();
if (!player.asPlayer().hasPermission("superiorskyblock.spy")) {
event.setCancelled(true);
return;
}
if (enabled) {
spyUsers.add(player.getUniqueId());
player.asPlayer().sendMessage("§cSpy mode enabled - you will see all island chats");
} else {
spyUsers.remove(player.getUniqueId());
player.asPlayer().sendMessage("§cSpy mode disabled");
}
}
}
Complete Event List
All player-specific events:
Role & Status
PlayerChangeRoleEvent - Player role changes
PlayerReplaceEvent - Player object replacement
Settings
PlayerChangeBorderColorEvent - Border color change
PlayerChangeLanguageEvent - Language preference change
PlayerChangeNameEvent - Display name change
Toggles
PlayerToggleBorderEvent - World border visibility toggle
PlayerToggleFlyEvent - Island fly mode toggle
PlayerToggleBypassEvent - Protection bypass toggle
PlayerTogglePanelEvent - Top panel toggle
PlayerToggleTeamChatEvent - Team chat toggle
PlayerToggleSpyEvent - Spy mode toggle
PlayerToggleBlocksStackerEvent - Block stacker toggle
PlayerOpenMenuEvent - Menu opened
PlayerCloseMenuEvent - Menu closed
Messages
AttemptPlayerSendMessageEvent - Before message sent to player
SendMessageEvent - Message sent to player
Best Practices
Player Event Guidelines:
- Always check permissions before allowing toggle features
- Validate player input in change events (name, language, etc.)
- Save player preferences to persistent storage
- Log important admin actions (bypass, spy mode)
- Consider economy costs for premium features
- Handle null cases when players might not be online
Next Steps