Skip to content

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.

License

Notifications You must be signed in to change notification settings

mattbaconz/IonAPI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

29 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

โšก IonAPI

Modern, Multi-Platform Minecraft Plugin API

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

Discord GitHub Ko-fi PayPal

Reduce boilerplate by 50-80% โ€ข Unified Paper/Folia API โ€ข Modern Fluent Design

๐Ÿ“š Documentation โ€ข ๐Ÿš€ Quick Start โ€ข ๐Ÿ’ก Examples โ€ข ๐Ÿค Contributing


โœจ Why IonAPI?

// โŒ Old Way (Bukkit API) - 15+ lines
ItemStack sword = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta meta = sword.getItemMeta();
if (meta != null) {
    meta.setDisplayName(ChatColor.RED + "Legendary Sword");
    List<String> lore = new ArrayList<>();
    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 lines
ItemStack sword = 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

Feature IonAPI Bukkit API Other 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.2.0 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.2.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.2.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.2.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.20.4-R0.1-SNAPSHOT")
    implementation("com.github.mattbaconz:IonAPI:1.2.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

import com.ionapi.api.IonPlugin;

public class MyPlugin implements IonPlugin {
    
    @Override
    public void onEnable() {
        getLogger().info("๐Ÿš€ MyPlugin enabled!");
        
        // Register commands
        getCommandRegistry().register(new HelloCommand());
        
        // Load config
        IonConfig config = getConfigProvider().getConfig();
        String message = config.getString("welcome-message");
    }
    
    @Override
    public void onDisable() {
        getScheduler().cancelAll();
        getLogger().info("๐Ÿ‘‹ MyPlugin disabled!");
    }
    
    @Override
    public String getName() {
        return "MyPlugin";
    }
}

2๏ธโƒฃ Create a Command

public class HelloCommand implements IonCommand {
    @Override
    public boolean execute(CommandContext ctx) {
        String name = ctx.getArg(0, "World");
        ctx.reply("<green>Hello, <bold>" + name + "</bold>!");
        return true;
    }
    
    @Override
    public String getName() { return "hello"; }
    @Override
    public String getDescription() { return "Greets a player"; }
    @Override
    public String getUsage() { return "/hello [name]"; }
    @Override
    public String getPermission() { 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.20.4-R0.1-SNAPSHOT")
    implementation("com.github.mattbaconz:IonAPI:1.2.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

ItemStack sword = 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 -> {
        Player player = 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.create(player)
    .title("<gold><bold>โšก Server Stats")
    .line("<gray>โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”")
    .line("")
    .line("")
    .dynamicLine(1, p -> "<yellow>Players: <white>" + Bukkit.getOnlinePlayers().size())
    .dynamicLine(2, p -> "<green>Health: <white>" + (int) p.getHealth() + "โค")
    .autoUpdate(20L)  // Updates every second
    .show();

๐Ÿ”— 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 seconds
public class PlayerData {
    @PrimaryKey private UUID uuid;
    @Column private String name;
    @Column private int level;
    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "guild_id")
    private Guild guild;
}

// Simple queries
PlayerData data = db.find(PlayerData.class, playerUuid);
data.setLevel(data.getLevel() + 1);
db.save(data);

// Async support
db.findAsync(PlayerData.class, uuid)
    .thenAccept(data -> processData(data));

๐Ÿ’ฐ Economy System

// Check balance
IonEconomy.getBalance(player.getUniqueId()).thenAccept(balance -> {
    player.sendMessage("Balance: " + IonEconomy.format(balance));
});

// Fluent transaction API
IonEconomy.transaction(player.getUniqueId())
    .withdraw(100)
    .reason("Shop purchase")
    .commit()
    .thenAccept(result -> {
        if (result.isSuccess()) {
            player.sendMessage("<green>Purchase complete!");
        }
    });

// Transfer between players
IonEconomy.transfer(sender, receiver, BigDecimal.valueOf(50));

๐Ÿ”ด Redis Pub/Sub

IonRedis redis = IonRedisBuilder.create()
    .host("localhost")
    .port(6379)
    .password("secret")
    .build();

// Subscribe to channel
redis.subscribe("player-events", message -> {
    String data = message.getData();
    Bukkit.broadcastMessage("Event: " + data);
});

// Publish message
redis.publish("player-events", "Player joined: " + player.getName());

// Key-value storage with TTL
redis.set("player:" + uuid, playerData, 3600); // Expires in 1 hour

๐Ÿ”ฅ Hot-Reload Config

HotReloadConfig config = 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

Feature Paper Folia
โšก 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-fi PayPal


๐ŸŒŸ Community

Discord GitHub

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

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages