Version: 1.5.0 | Quick, practical examples to get you started fast.
ItemStack sword = IonItem.builder(Material.DIAMOND_SWORD)
.name("<red>Legendary Sword")
.lore("<gray>Forged in dragon fire")
.enchant(Enchantment.SHARPNESS, 5)
.unbreakable()
.build();ItemStack item = IonItem.builder(Material.DIAMOND_SWORD)
.name("<gradient:red:blue><bold>Flame Reaver")
.lore(
"<gray>Forged in dragon fire",
"",
"<red>+ 15 Damage",
"<gold>+ 10% Critical Strike"
)
.enchant(Enchantment.SHARPNESS, 5)
.enchant(Enchantment.FIRE_ASPECT, 2)
.unbreakable()
.glow()
.hideAll()
.build();public void openShop(Player player) {
IonGui.builder()
.title("<gold><bold>✨ Shop")
.rows(3)
.item(11, IonItem.of(Material.DIAMOND, "<aqua>Diamond", "<gray>Price: $100"),
click -> {
if (buyItem(click.getPlayer(), 100)) {
click.getPlayer().sendMessage("<green>✓ Purchased!");
click.close();
} else {
click.getPlayer().sendMessage("<red>✗ Not enough money!");
}
})
.item(13, IonItem.of(Material.GOLD_INGOT, "<yellow>Gold", "<gray>Price: $50"),
click -> buyItem(click.getPlayer(), 50))
.fillBorderBuilder(IonItem.of(Material.GRAY_STAINED_GLASS_PANE, " "))
.build()
.open(player);
}public void openProfile(Player player) {
ItemStack profile = IonItem.builder(Material.PLAYER_HEAD)
.name("<gold><bold>" + player.getName())
.lore(
"<gray>Your Profile",
"",
"<yellow>Level: <white>" + getLevel(player),
"<green>Coins: <white>" + getCoins(player)
)
.glow()
.build();
IonGui.builder()
.title("<gold>Your Profile")
.rows(3)
.item(13, profile)
.fillBorderBuilder(IonItem.of(Material.BLUE_STAINED_GLASS_PANE, " "))
.build()
.open(player);
}private final Map<UUID, IonScoreboard> scoreboards = new HashMap<>();
public void showStatsBoard(Player player) {
IonScoreboard board = IonScoreboard.builder()
.title("<gold><bold>⚡ Your Stats")
.line(15, "<gray>━━━━━━━━━━━━━━")
.line(14, "<yellow>Level: <white>{level}")
.line(13, "<green>Coins: <white>{coins}")
.line(12, "<aqua>Rank: <white>{rank}")
.line(11, "<gray>━━━━━━━━━━━━━━")
.placeholder("level", p -> String.valueOf(getLevel(p)))
.placeholder("coins", p -> String.valueOf(getCoins(p)))
.placeholder("rank", p -> getRank(p))
.updateInterval(20) // Auto-update every second
.build();
board.show(player);
scoreboards.put(player.getUniqueId(), board);
}
@Override
public void onDisable() {
scoreboards.values().forEach(IonScoreboard::destroy);
}IonScoreboard.builder()
.title("<gradient:gold:yellow>My Server")
.animatedLine(15, 10, "✦ Welcome ✦", "★ Welcome ★", "✧ Welcome ✧")
.line(14, "")
.line(13, "<yellow>Players: <white>{online}")
.placeholder("online", p -> String.valueOf(Bukkit.getOnlinePlayers().size()))
.updateInterval(20)
.build()
.show(player);@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
TaskChain.create(plugin)
.async(() -> database.loadPlayerData(player.getUniqueId()))
.syncAt(player, data -> {
if (data != null) {
player.setLevel(data.level);
player.sendMessage("<green>✓ Data loaded!");
} else {
createNewPlayer(player);
}
})
.exceptionally(ex -> {
player.sendMessage("<red>✗ Failed to load data!");
getLogger().severe("Error: " + ex.getMessage());
})
.execute();
}private void purchaseItem(Player player, Material item, int cost) {
TaskChain.create(plugin)
.async(() -> economy.getBalance(player.getUniqueId()))
.syncAt(player, balance -> {
if (balance >= cost) {
economy.withdraw(player.getUniqueId(), cost);
player.getInventory().addItem(new ItemStack(item));
player.sendMessage("<green>✓ Purchase successful!");
} else {
player.sendMessage("<red>✗ Not enough money!");
}
})
.execute();
}// ✅ Folia-safe - runs on player's region thread
getScheduler().runAt(player, () -> {
player.damage(5.0);
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 200, 1));
});
// Delayed
getScheduler().runAtLater(player, () -> {
player.sendMessage("<yellow>5 seconds passed!");
}, 5, TimeUnit.SECONDS);// ✅ Folia-safe - runs on location's region thread
Location spawn = world.getSpawnLocation();
getScheduler().runAt(spawn, () -> {
world.spawnParticle(Particle.FLAME, spawn, 10);
world.createExplosion(spawn, 4.0f);
});public class MyPlugin implements IonPlugin {
private final Map<UUID, IonScoreboard> scoreboards = new HashMap<>();
@Override
public void onEnable() {
// Register commands
getCommandRegistry().register(new ShopCommand(this));
// Register events
Bukkit.getPluginManager().registerEvents(new JoinListener(this), this);
getLogger().info("✓ Plugin enabled!");
}
@Override
public void onDisable() {
scoreboards.values().forEach(IonScoreboard::destroy);
scoreboards.clear();
getScheduler().cancelAll();
}
@Override
public String getName() {
return "MyPlugin";
}
private class JoinListener implements Listener {
private final MyPlugin plugin;
public JoinListener(MyPlugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
// Show scoreboard
IonScoreboard board = IonScoreboard.builder()
.title("<gold>Welcome!")
.line(15, "<yellow>Players: {players}")
.placeholder("players", p -> String.valueOf(Bukkit.getOnlinePlayers().size()))
.updateInterval(20)
.build();
board.show(player);
scoreboards.put(player.getUniqueId(), board);
}
}
private class ShopCommand implements IonCommand {
private final MyPlugin plugin;
public ShopCommand(MyPlugin plugin) {
this.plugin = plugin;
}
@Override
public boolean execute(CommandContext ctx) {
Player player = (Player) ctx.getSender();
IonGui.builder()
.title("<gold>Shop")
.rows(3)
.item(13, IonItem.of(Material.DIAMOND, "<aqua>Diamond - $100"),
click -> {
click.getPlayer().sendMessage("<green>Purchased!");
click.close();
})
.fillBorderBuilder(IonItem.of(Material.GRAY_STAINED_GLASS_PANE, " "))
.build()
.open(player);
return true;
}
@Override
public String getName() { return "shop"; }
@Override
public String getDescription() { return "Open shop"; }
@Override
public String getUsage() { return "/shop"; }
@Override
public String getPermission() { return "myplugin.shop"; }
}
}For more detailed examples, see:
- Getting Started Guide - Complete tutorial
- API Reference - Full API documentation
- Quick Reference - Quick cheatsheet
Need help? Join our Discord!
// Simple confirmation
ConfirmationGui.create()
.title("<red>⚠ Confirm")
.message("Delete all data?")
.onConfirm(player -> {
deleteData();
player.sendMessage("<green>Deleted!");
})
.onCancel(player -> player.sendMessage("Cancelled"))
.open(player);
// Danger styling
ConfirmationGui.create()
.message("This cannot be undone!")
.danger()
.onConfirm(player -> dangerousAction())
.open(player);ItemStack customHead = IonItem.builder(Material.PLAYER_HEAD)
.skullTexture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy4uLiJ9fX0=")
.name("<gold>Custom NPC Head")
.build();ItemStack armor = IonItem.builder(Material.LEATHER_CHESTPLATE)
.color(Color.fromRGB(255, 100, 50))
.name("<gradient:red:orange>Fire Armor")
.glow()
.build();ItemStack superPotion = IonItem.builder(Material.POTION)
.potionType(PotionType.STRENGTH)
.potionEffect(PotionEffectType.SPEED, 600, 2)
.potionEffect(PotionEffectType.REGENERATION, 600, 1)
.potionColor(Color.PURPLE)
.name("<purple>Super Potion")
.lore("<gray>Speed III + Regen II")
.build();CooldownManager teleportCooldown = CooldownManager.create("teleport");
if (teleportCooldown.isOnCooldown(player.getUniqueId())) {
long remaining = teleportCooldown.getRemainingTime(player.getUniqueId(), TimeUnit.SECONDS);
player.sendMessage("Wait " + remaining + "s before teleporting!");
return;
}
// Perform teleport...
teleportCooldown.setCooldown(player.getUniqueId(), 30, TimeUnit.SECONDS);// Allow 5 messages per 10 seconds
RateLimiter chatLimiter = RateLimiter.create("chat", 5, 10, TimeUnit.SECONDS);
if (!chatLimiter.tryAcquire(player.getUniqueId())) {
player.sendMessage("Slow down! You're sending messages too fast.");
return;
}
// Process message...// Simple message
MessageBuilder.of("<green>Welcome back, <player>!")
.placeholder("player", player.getName())
.send(player);
// Title with subtitle
MessageBuilder.of("<gold><bold>LEVEL UP!")
.subtitle("<gray>You are now level <level>")
.placeholder("level", "10")
.sendTitle(player);
// Action bar
MessageBuilder.of("<red>❤ <health>/<max_health>")
.placeholder("health", "15")
.placeholder("max_health", "20")
.sendActionBar(player);IonScoreboard board = IonScoreboard.builder()
.title("<gradient:gold:yellow><bold>My Server")
.line(15, "<gray>Welcome, <white>{player}")
.line(14, "")
.line(13, "<gold>Coins: <yellow>{coins}")
.line(12, "<green>Online: <white>{online}")
.placeholder("player", p -> p.getName())
.placeholder("coins", p -> "1,234")
.placeholder("online", p -> String.valueOf(Bukkit.getOnlinePlayers().size()))
.build();
board.show(player);IonBossBar bar = IonBossBar.builder()
.title("<gradient:red:orange>Event Progress: {progress}%")
.color(BossBar.Color.RED)
.progress(0.5f)
.placeholder("progress", p -> "50")
.build();
bar.show(player);
bar.setProgress(0.75f); // Update progressList<PlayerStats> stats = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
stats.add(new PlayerStats(UUID.randomUUID(), 0, 0));
}
// 10-50x faster than individual inserts!
BatchOperation.BatchResult result = database.batch(PlayerStats.class)
.insertAll(stats)
.batchSize(500)
.execute();
System.out.println("Inserted " + result.insertedCount() + " records in " + result.executionTimeMs() + "ms");// Count events
Metrics.increment("player.join");
Metrics.increment("commands.executed");
// Set gauge values
Metrics.gauge("players.online", Bukkit.getOnlinePlayers().size());
// Time operations
String result = Metrics.time("database.query", () -> {
return database.findAll(PlayerData.class);
});
// Get statistics
double avgTime = Metrics.getAverageTime("database.query");
System.out.println("Average query time: " + avgTime + "ms");See examples/V120FeaturesExample.java for complete working examples of all v1.2.0 features.