Skip to content

Latest commit

History

53 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

⚡ IonAPI

Modern, Multi-Platform Minecraft Plugin API

Write less code. Build better plugins. Support Paper & Folia.

DiscordGitHubKo-fiPayPal

Reduce boilerplate by 50-80%Unified Paper/Folia APIModern Fluent Design

📚 Documentation🚀 Quick Start💡 Examples🤝 Contributing


✨ Why IonAPI?

// ❌ Old Way (Bukkit API) - 15+ linesItemStacksword = newItemStack(Material.DIAMOND_SWORD);
ItemMetameta = sword.getItemMeta();
if (meta != null) {
meta.setDisplayName(ChatColor.RED + "Legendary Sword");
List<String> lore = newArrayList<>();
lore.add(ChatColor.GRAY + "Forged in dragon fire");
meta.setLore(lore);
meta.addEnchant(Enchantment.SHARPNESS, 5, false);
meta.setUnbreakable(true);
}
sword.setItemMeta(meta);
// ✅ New Way (IonAPI) - 6 linesItemStacksword = IonItem.builder(Material.DIAMOND_SWORD)
.name("<red>Legendary Sword")
.lore("<gray>Forged in dragon fire")
.enchant(Enchantment.SHARPNESS, 5)
.unbreakable()
.build();

60% less code. 100% more readable. Fully type-safe.


📊 IonAPI vs Others

FeatureIonAPIBukkit APIOther Libraries
Folia Support✅ Native❌ No⚠️ Partial
Async ORM✅ Built-in + Caching❌ No⚠️ Basic
Economy API✅ Vault + Async❌ No⚠️ Vault only
Redis Support✅ Pub/Sub + KV❌ No❌ Rare
Hot-Reload Config✅ WatchService❌ Manual❌ Manual
Item Builder✅ MiniMessage⚠️ Legacy colors✅ Varies
GUI System✅ Fluent + Pagination❌ Manual✅ Varies
Task Chains✅ Async/Sync⚠️ Basic⚠️ Limited
Testing Framework✅ Mocks included❌ No❌ Rare
Learning Curve🟢 Low🟡 Medium🟡 Varies
Code Reduction🟢 50-80%-🟡 30-50%

🎯 Features

🔥 Core Features

  • Unified Scheduler - Paper & Folia compatible
  • 🎮 Modern Commands - Fluent registration
  • ⚙️ Smart Config - Type-safe configuration
  • 📢 Event Bus - Custom event system
  • 🛠️ Utilities - MiniMessage support

🆕 Extended Features

  • 🎨 Item Builder - Fluent ItemStack creation
  • 📦 GUI System - Interactive menus
  • 📊 Scoreboard/BossBar - Dynamic UI
  • 🔗 Task Chains - Async/sync workflows
  • 💾 Database ORM - Simple data persistence

🌟 Additional Modules

  • 💰 Economy System - Vault-compatible with async API (~14 KB)
  • 🔴 Redis Integration - Pub/sub messaging + KV storage (~9 KB + Lettuce)
  • 🔥 Hot-Reload Config - Auto-reload on file changes (built-in)
  • 🔌 Cross-Server Messaging - Velocity/BungeeCord support (~11 KB)
  • 👻 Packet NPCs - Lightweight, zero-tick NPCs (~24 KB)
  • 🏷️ PlaceholderAPI Bridge - Auto-registration (~7 KB)
  • 💉 Dependency Injection - Clean architecture (~6 KB)
  • 🧪 Unit Testing - Mock framework (~21 KB)
  • 🔄 Compatibility Layer - Java 8+ polyfills (~38 KB)

🚀 v1.5.0 Features (Enterprise-Grade)

  • 📢 Working Event Bus - Real in-memory event dispatcher with priority sorting
  • 💾 SQL Injection Protection - Identifier quoting (backticks) for all table/column names
  • 💉 Advanced DI - Constructor injection support + Circular dependency detection
  • 💾 No Thread Starvation - Dedicated database executors for all async operations
  • 👻 NPC Bridge Pattern - Refactored to NmsAdapter interface for modularity

🆕 v1.3.0 Features

  • 📊 Scoreboard Fix - No more flashing on updates
  • Animated Lines - Cycling scoreboard text
  • ConfirmationGui - Simple yes/no dialogs
  • 💀 Skull Textures - Custom head textures via base64
  • 🎨 Leather Colors - Colored leather armor
  • 🧪 Potion Effects - Fluent potion builder

🔧 v1.2.6 Features

  • ⏱️ CooldownManager - Thread-safe player cooldowns
  • 🚦 RateLimiter - Sliding window rate limiting
  • 💬 MessageBuilder - Fluent MiniMessage builder with templates
  • 📊 IonScoreboard - Easy scoreboard creation
  • 📈 IonBossBar - Boss bar management
  • 📉 Metrics - Lightweight performance monitoring
  • BatchOperation - 10-50x faster bulk database operations
  • 🔄 ReflectionCache - Cached entity metadata for ORM

Total size (all modules): ~260 KB - Smaller than most images!


📦 Installation

💡 Easy Shading: IonAPI is designed to be easily shadable! Just add the Shadow plugin and dependency - no complex configuration needed.

Gradle (Kotlin DSL) - Recommended ⭐

plugins {
id("com.gradleup.shadow") version "8.3.0"
}
repositories {
mavenCentral()
maven("https://jitpack.io")
}
dependencies {
// IonAPI automatically shades into your plugin!
implementation("com.github.mattbaconz:IonAPI:1.5.0")
}
tasks.shadowJar {
// ⚠️ IMPORTANT: Relocate to avoid conflicts!
relocate("com.ionapi", "your.plugin.libs.ionapi")
// Optional: Minimize JAR size
minimize()
}

✨ That's it! IonAPI is designed to be easily shadable. Just add the dependency and Shadow plugin handles the rest!

Gradle (Groovy)

plugins {
id 'com.gradleup.shadow' version '8.3.0'
}
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.mattbaconz:IonAPI:1.5.0'
}
shadowJar {
relocate 'com.ionapi', 'your.plugin.libs.ionapi'
}

Maven

<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.mattbaconz</groupId>
<artifactId>IonAPI</artifactId>
<version>1.5.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<relocations>
<relocation>
<pattern>com.ionapi</pattern>
<shadedPattern>your.plugin.libs.ionapi</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

💡 Pro Tip: Always relocate IonAPI to avoid conflicts when multiple plugins use different versions! For detailed instructions, module sizes, and dependency graphs, see the Shading Guide.

🎯 Shading Made Easy

IonAPI is designed for easy adoption with minimal configuration:

✅ What you get:

  • 📦 Single JAR - Everything bundled together
  • 🔒 Conflict-free - Proper relocation prevents issues
  • 🪶 Lightweight - Only ~300KB when shaded
  • Fast - No runtime dependencies to load
  • 🎯 Simple - Just add Shadow plugin and dependency

Example: Complete build.gradle.kts

plugins {
java
id("com.gradleup.shadow") version "8.3.0"
}
group ="com.example"
version ="1.0.0"
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://jitpack.io")
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT")
implementation("com.github.mattbaconz:IonAPI:1.5.0")
}
tasks {
shadowJar {
archiveClassifier.set("")
relocate("com.ionapi", "${project.group}.libs.ionapi")
minimize() // Optional: Reduce JAR size
}
build {
dependsOn(shadowJar)
}
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}

Build your plugin:

./gradlew shadowJar
# Your plugin JAR with IonAPI included: build/libs/YourPlugin-1.0.0.jar

🚀 Quick Start

1️⃣ Create Your Plugin

importcom.ionapi.api.IonPlugin;
publicclassMyPluginimplementsIonPlugin {
@OverridepublicvoidonEnable() {
getLogger().info("🚀 MyPlugin enabled!");
// Register commandsgetCommandRegistry().register(newHelloCommand());
// Load configIonConfigconfig = getConfigProvider().getConfig();
Stringmessage = config.getString("welcome-message");
}
@OverridepublicvoidonDisable() {
getScheduler().cancelAll();
getLogger().info("👋 MyPlugin disabled!");
}
@OverridepublicStringgetName() {
return"MyPlugin";
}
}

2️⃣ Create a Command

publicclassHelloCommandimplementsIonCommand {
@Overridepublicbooleanexecute(CommandContextctx) {
Stringname = ctx.getArg(0, "World");
ctx.reply("<green>Hello, <bold>" + name + "</bold>!");
returntrue;
}
@OverridepublicStringgetName() { return"hello"; }
@OverridepublicStringgetDescription() { return"Greets a player"; }
@OverridepublicStringgetUsage() { return"/hello [name]"; }
@OverridepublicStringgetPermission() { return"myplugin.hello"; }
}

3️⃣ Configure Shading (build.gradle.kts)

plugins {
java
id("com.gradleup.shadow") version "8.3.0"
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT")
implementation("com.github.mattbaconz:IonAPI:1.5.0")
}
tasks.shadowJar {
archiveClassifier.set("")
// ⚠️ CRITICAL: Always relocate to avoid conflicts
relocate("com.ionapi", "com.yourname.yourplugin.libs.ionapi")
minimize()
}

4️⃣ Build & Run

./gradlew shadowJar
# Copy build/libs/YourPlugin-1.0.0.jar to server/plugins/

That's it! 🎉

💡 Why relocate? Prevents conflicts when multiple plugins use IonAPI. See SHADING_GUIDE.md for details.


💡 Feature Showcase

🎨 Item Builder

ItemStacksword = IonItem.builder(Material.DIAMOND_SWORD)
.name("<gradient:red:blue>Legendary Sword")
.lore(
"<gray>Forged in dragon fire",
"",
"<gold>⚔ Legendary Weapon"
)
.enchant(Enchantment.SHARPNESS, 5)
.enchant(Enchantment.FIRE_ASPECT, 2)
.unbreakable()
.glow()
.build();

📦 GUI System

IonGui.builder()
.title("<gold><bold>✨ Shop Menu")
.rows(3)
.item(10, diamondItem, click -> {
Playerplayer = click.getPlayer();
if (buyItem(player, 100)) {
player.sendMessage("<green>✓ Purchased!");
click.close();
} else {
player.sendMessage("<red>✗ Not enough money!");
}
})
.fillBorderBuilder(IonItem.of(Material.GRAY_STAINED_GLASS_PANE, " "))
.build()
.open(player);

📊 Dynamic Scoreboard

IonScoreboard.builder()
.title("<gold><bold>⚡ Server Stats")
.line(15, "<gray>━━━━━━━━━━━━━━")
.line(14, "<yellow>Players: <white>{players}")
.line(13, "<green>Health: <white>{health}")
.line(12, "")
.line(11, "<aqua>example.com")
.placeholder("players", p -> String.valueOf(Bukkit.getOnlinePlayers().size()))
.placeholder("health", p -> String.valueOf((int) p.getHealth()) + "❤")
.updateInterval(20) // Updates every second
.fixedWidth(20) // Prevents width changes
.build()
.show(player);

🔗 Task Chains (Async/Sync)

TaskChain.create(plugin)
.async(() -> database.loadPlayerData(uuid))
.syncAt(player, data -> {
player.setLevel(data.level);
player.sendMessage("<green>✓ Data loaded!");
})
.delay(2, TimeUnit.SECONDS)
.syncAt(player, () -> player.sendMessage("<gold>Welcome back!"))
.exceptionally(ex -> player.sendMessage("<red>✗ Failed to load data!"))
.execute();

💾 Database ORM

@Table("players")
@Cacheable(ttl = 60) // Cache for 60 secondspublicclassPlayerData {
@PrimaryKeyprivateUUIDuuid;
@ColumnprivateStringname;
@Columnprivateintlevel;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "guild_id")
privateGuildguild;
}
// Simple queriesPlayerDatadata = db.find(PlayerData.class, playerUuid);
data.setLevel(data.getLevel() + 1);
db.save(data);
// Async supportdb.findAsync(PlayerData.class, uuid)
.thenAccept(data -> processData(data));

💰 Economy System

// Check balanceIonEconomy.getBalance(player.getUniqueId()).thenAccept(balance -> {
player.sendMessage("Balance: " + IonEconomy.format(balance));
});
// Fluent transaction APIIonEconomy.transaction(player.getUniqueId())
.withdraw(100)
.reason("Shop purchase")
.commit()
.thenAccept(result -> {
if (result.isSuccess()) {
player.sendMessage("<green>Purchase complete!");
}
});
// Transfer between playersIonEconomy.transfer(sender, receiver, BigDecimal.valueOf(50));

🔴 Redis Pub/Sub

IonRedisredis = IonRedisBuilder.create()
.host("localhost")
.port(6379)
.password("secret")
.build();
// Subscribe to channelredis.subscribe("player-events", message -> {
Stringdata = message.getData();
Bukkit.broadcastMessage("Event: " + data);
});
// Publish messageredis.publish("player-events", "Player joined: " + player.getName());
// Key-value storage with TTLredis.set("player:" + uuid, playerData, 3600); // Expires in 1 hour

🔥 Hot-Reload Config

HotReloadConfigconfig = HotReloadConfig.create(this, "config.yml")
.onReload(cfg -> {
welcomeMessage = cfg.getString("welcome-message");
maxPlayers = cfg.getInt("max-players");
getLogger().info("Config reloaded!");
})
.start();
// Edit config.yml while server is running - changes apply instantly!

🎯 Platform Compatibility

FeaturePaperFolia
⚡ Scheduler✅ Main thread✅ Region-aware
🎮 Commands
⚙️ Configuration
📢 Events
🛠️ Utilities
🎨 Item Builder
📦 GUI System
📊 UI Components
🔗 Task Chains✅ Folia-optimized

📚 Documentation

📖 Getting Started

💡 Learn More

🔧 Advanced


🏗️ Project Structure

IonAPI/
├── 🎯 ion-api/ Core API interfaces
├── ⚙️ ion-core/ Base implementations
├── 🎨 ion-item/ Item Builder
├── 📦 ion-gui/ GUI System
├── 📊 ion-ui/ Scoreboard & BossBar
├── 🔗 ion-tasks/ Task Chains
├── 💾 ion-database/ Database ORM + Caching
├── 💰 ion-economy/ Economy API + Vault hook
├── 🔴 ion-redis/ Redis pub/sub + KV store
├── 🔌 ion-proxy/ Cross-server messaging
├── 👻 ion-npc/ Packet NPCs
├── 🏷️ ion-placeholder/ PlaceholderAPI bridge
├── 💉 ion-inject/ Dependency injection
├── 🧪 ion-test/ Testing framework
├── 🔄 ion-compat/ Compatibility layer
└── 🖥️ platforms/ Paper & Folia implementations

🤝 Contributing

We love contributions! Whether it's:

  • 🐛 Bug reports
  • 💡 Feature requests
  • 📝 Documentation improvements
  • 🔧 Code contributions

Check out our Contributing Guide to get started!


💖 Support the Project

If IonAPI helps you build better plugins, consider supporting development:

Ko-fiPayPal


🌟 Community

DiscordGitHub

Join our Discord for:

  • 💬 Plugin development help
  • 🐛 Bug reports & support
  • 💡 Feature discussions
  • 🎉 Community showcase

📜 License

IonAPI is open source software licensed under the MIT License.


🙏 Acknowledgments

Built with ❤️ by mattbaconz

Special thanks to:

  • 🎮 PaperMC - For the amazing Paper & Folia platforms
  • 🎨 Adventure API - For modern text components
  • 🌟 All contributors - For making IonAPI better

⭐ Star this repo if you find it useful!

Made with ❤️ for the Minecraft plugin development community

📚 Documentation💡 Examples🐛 Report Bug💬 Discord

About

Modern, multi-platform Minecraft plugin API for Paper and Folia. Reduces boilerplate by 50-80% with fluent APIs, unified scheduler, and built-in GUI/Scoreboard/Database systems.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages