Compatibility
Minecraft: Java Edition
Platforms
Creators
Details
XoperrCore API
Core API library for BlissGems and other XoperrDev plugins. Provides four main APIs:
- Gem Protection API - Prevent items from being dropped or moved
- Custom Particle API - Create custom particles using Display entities
- Inventory Text API - Display custom text when items are held
- Auto-Enchant API - Automatically apply enchantments to gear when gems are in inventory
Requirements
- Minecraft 1.21.x
- Paper or Purpur server
- Java 21
Building
mvn clean package
The compiled JAR will be in target/XoperrCore-1.0.0.jar
Installation
- Download or build the plugin JAR
- Place in your server's
plugins/folder - Restart the server
API Usage
1. Gem Protection API
Prevent items (gems) from being dropped, stored in chests, or used in grindstones/anvils.
import com.xoperr.core.api.protection.GemProtectionAPI;
import org.bukkit.inventory.ItemStack;
import org.bukkit.Material;
// Mark an item as a gem (basic)
ItemStack gem = new ItemStack(Material.DIAMOND);
GemProtectionAPI.markAsGem(gem);
// Mark an item as a gem with metadata
GemProtectionAPI.markAsGem(gem, "fire", 1); // gemId: "fire", tier: 1
// Check if an item is a gem
boolean isGem = GemProtectionAPI.isGem(gem); // true
// Get gem metadata
String gemId = GemProtectionAPI.getGemId(gem); // "fire"
int tier = GemProtectionAPI.getGemTier(gem); // 1
// Remove gem protection
GemProtectionAPI.unmarkGem(gem);
What's Protected:
- ❌ Cannot drop gems
- ❌ Cannot store in chests/barrels/hoppers/shulker boxes
- ❌ Cannot use in grindstones/anvils/enchanting tables
- ❌ Cannot put in furnaces/brewing stands
- ✅ Can equip in armor slots or offhand
- ✅ Can move within player inventory
2. Custom Particle API
Create custom particles using Display entities and resource pack models.
import com.xoperr.core.api.particle.ParticleAPI;
import com.xoperr.core.api.particle.CustomParticle;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Display;
// Create a custom particle
CustomParticle particle = ParticleAPI.create("flame_burst")
.material(Material.PAPER) // Base material
.customModelData(1001) // Model ID from resource pack
.scale(0.8f) // Size (1.0 = normal)
.brightness(15, 15) // Block light, sky light (0-15)
.viewRange(64.0f) // View distance in blocks
.billboard(Display.Billboard.CENTER) // How it faces players
.interpolationDuration(10) // Smooth animation (ticks)
.spawn(location); // Spawn at location
// Move the particle
particle.teleport(newLocation);
// Animate scale
particle.setScale(1.5f);
particle.setInterpolationDuration(20); // Smooth resize over 20 ticks
// Adjust brightness
particle.setBrightness(10, 15);
// Remove the particle
particle.remove();
// Get active particle count
int count = ParticleAPI.getActiveParticleCount();
// Remove all particles
ParticleAPI.removeAllParticles();
Resource Pack Setup:
Create a resource pack with custom models:
assets/
xoperrcore/
models/
item/
flame_particle.json
In your item model JSON:
{
"parent": "item/generated",
"textures": {
"layer0": "xoperrcore:item/flame_particle"
}
}
Then reference it with customModelData:
.material(Material.PAPER)
.customModelData(1001)
3. Inventory Text API
Display custom text when players hold specific items.
Basic Usage (Direct)
import com.xoperr.core.api.text.InventoryTextAPI;
import org.bukkit.entity.Player;
// Send action bar text
InventoryTextAPI.sendActionBar(player, "§6⚡ Speed Gem Active");
// Clear action bar
InventoryTextAPI.clearActionBar(player);
// Send title
InventoryTextAPI.sendTitle(
player,
"§cFire Gem", // Title
"§7Right-click to shoot", // Subtitle
10, // Fade in (ticks)
70, // Stay (ticks)
20 // Fade out (ticks)
);
// Clear title
InventoryTextAPI.clearTitle(player);
Advanced Usage (Provider System)
Create a provider to automatically show text when players hold specific items:
import com.xoperr.core.api.text.InventoryTextAPI;
import com.xoperr.core.api.text.InventoryTextProvider;
import com.xoperr.core.api.protection.GemProtectionAPI;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class GemTextProvider implements InventoryTextProvider {
@Override
public String getActionBarText(Player player, ItemStack mainHand, ItemStack offHand) {
// Check main hand
if (mainHand != null && GemProtectionAPI.isGem(mainHand)) {
String gemId = GemProtectionAPI.getGemId(mainHand);
int tier = GemProtectionAPI.getGemTier(mainHand);
return "§6⚡ " + capitalize(gemId) + " Gem §7(Tier " + tier + ")";
}
// Check offhand
if (offHand != null && GemProtectionAPI.isGem(offHand)) {
String gemId = GemProtectionAPI.getGemId(offHand);
return "§e✦ " + capitalize(gemId) + " Gem (Offhand)";
}
return null; // No text to display
}
@Override
public boolean shouldUpdate(Player player, ItemStack mainHand, ItemStack offHand) {
// Only update if player is holding a gem
return GemProtectionAPI.isGem(mainHand) || GemProtectionAPI.isGem(offHand);
}
@Override
public int getPriority() {
return 10; // Higher priority = checked first
}
private String capitalize(String str) {
if (str == null || str.isEmpty()) return str;
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
// Register the provider (in your plugin's onEnable)
InventoryTextAPI.registerTextProvider(new GemTextProvider());
// Unregister when done (in onDisable)
InventoryTextAPI.unregisterTextProvider(provider);
The provider system automatically updates action bar text every 5 ticks (4 times per second) for all online players.
4. Auto-Enchant API
Automatically apply enchantments to a player's equipped gear when they have specific gems in their inventory.
Basic Usage
import com.xoperr.core.api.enchant.AutoEnchantAPI;
import com.xoperr.core.api.enchant.EnchantmentRule;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.EquipmentSlot;
// Create a rule for the Fire gem
EnchantmentRule fireRule = new EnchantmentRule("fire")
.addArmorEnchantment(Enchantment.FIRE_PROTECTION, 4) // All armor pieces
.addWeaponEnchantment(Enchantment.FIRE_ASPECT, 2); // Main hand weapon
// Register the rule (in your plugin's onEnable)
AutoEnchantAPI.registerRule(fireRule);
// Create a rule for the Speed gem
EnchantmentRule speedRule = new EnchantmentRule("speed")
.addEnchantment(EquipmentSlot.FEET, Enchantment.SWIFT_SNEAK, 3)
.addEnchantment(EquipmentSlot.FEET, Enchantment.DEPTH_STRIDER, 3)
.addEnchantment(EquipmentSlot.LEGS, Enchantment.PROTECTION, 2);
AutoEnchantAPI.registerRule(speedRule);
// Create a rule for the Strength gem
EnchantmentRule strengthRule = new EnchantmentRule("strength")
.addWeaponEnchantment(Enchantment.SHARPNESS, 5)
.addWeaponEnchantment(Enchantment.KNOCKBACK, 2)
.addArmorEnchantment(Enchantment.PROTECTION, 3);
AutoEnchantAPI.registerRule(strengthRule);
Advanced Configuration
// Create a rule with priority and override settings
EnchantmentRule astraRule = new EnchantmentRule("astra")
.addEnchantment(EquipmentSlot.HAND, Enchantment.POWER, 5)
.addEnchantment(EquipmentSlot.HAND, Enchantment.INFINITY, 1)
.setPriority(10) // Higher priority = applied first
.setOverrideExisting(false); // Don't override player's own enchants
AutoEnchantAPI.registerRule(astraRule);
// Force update a player's enchantments manually
AutoEnchantAPI.updatePlayer(player);
// Remove all auto-enchants from a player
AutoEnchantAPI.clearPlayerEnchantments(player);
// Check if a rule exists
boolean hasRule = AutoEnchantAPI.hasRule("fire");
// Get a registered rule
EnchantmentRule rule = AutoEnchantAPI.getRule("speed");
// Unregister a rule
AutoEnchantAPI.unregisterRule("fire");
// Enable/disable the system globally
AutoEnchantAPI.setEnabled(false); // Disables and removes all auto-enchants
AutoEnchantAPI.setEnabled(true); // Re-enables
How It Works
- Automatic Detection: The system checks player inventories every 10 ticks (0.5 seconds)
- Gem Detection: When a player has a gem in their inventory (anywhere, not just equipped)
- Enchant Application: Enchantments are automatically applied to the corresponding equipment slots
- Smart Tracking: Uses PersistentDataContainer to track which enchants are "auto-applied"
- Removal: When the gem is removed from inventory, auto-enchants are removed
- Non-Destructive: Does not remove or override player's own enchantments
Equipment Slot Options
// Individual slots
.addEnchantment(EquipmentSlot.HEAD, enchant, level) // Helmet
.addEnchantment(EquipmentSlot.CHEST, enchant, level) // Chestplate
.addEnchantment(EquipmentSlot.LEGS, enchant, level) // Leggings
.addEnchantment(EquipmentSlot.FEET, enchant, level) // Boots
.addEnchantment(EquipmentSlot.HAND, enchant, level) // Main hand
.addEnchantment(EquipmentSlot.OFF_HAND, enchant, level) // Off hand
// Convenience methods
.addArmorEnchantment(enchant, level) // All 4 armor pieces
.addWeaponEnchantment(enchant, level) // Main hand only
Example: Complete Gem System
public class GemEnchantments {
public static void registerAllGemEnchantments() {
// Fire Gem - Fire protection and fire damage
AutoEnchantAPI.registerRule(new EnchantmentRule("fire")
.addArmorEnchantment(Enchantment.FIRE_PROTECTION, 4)
.addWeaponEnchantment(Enchantment.FIRE_ASPECT, 2));
// Speed Gem - Movement speed
AutoEnchantAPI.registerRule(new EnchantmentRule("speed")
.addEnchantment(EquipmentSlot.FEET, Enchantment.SWIFT_SNEAK, 3)
.addEnchantment(EquipmentSlot.FEET, Enchantment.DEPTH_STRIDER, 3)
.addEnchantment(EquipmentSlot.FEET, Enchantment.FEATHER_FALLING, 4));
// Strength Gem - Combat power
AutoEnchantAPI.registerRule(new EnchantmentRule("strength")
.addWeaponEnchantment(Enchantment.SHARPNESS, 5)
.addWeaponEnchantment(Enchantment.KNOCKBACK, 2)
.addArmorEnchantment(Enchantment.PROTECTION, 3));
// Life Gem - Durability and protection
AutoEnchantAPI.registerRule(new EnchantmentRule("life")
.addArmorEnchantment(Enchantment.PROTECTION, 4)
.addArmorEnchantment(Enchantment.UNBREAKING, 3)
.addWeaponEnchantment(Enchantment.UNBREAKING, 3));
// Wealth Gem - Looting and fortune
AutoEnchantAPI.registerRule(new EnchantmentRule("wealth")
.addWeaponEnchantment(Enchantment.LOOTING, 3)
.addEnchantment(EquipmentSlot.HAND, Enchantment.FORTUNE, 3));
// Astra Gem - Projectile power
AutoEnchantAPI.registerRule(new EnchantmentRule("astra")
.addWeaponEnchantment(Enchantment.POWER, 5)
.addWeaponEnchantment(Enchantment.PUNCH, 2)
.addWeaponEnchantment(Enchantment.INFINITY, 1));
// Puff Gem - Fall protection and feather falling
AutoEnchantAPI.registerRule(new EnchantmentRule("puff")
.addEnchantment(EquipmentSlot.FEET, Enchantment.FEATHER_FALLING, 4)
.addEnchantment(EquipmentSlot.CHEST, Enchantment.BLAST_PROTECTION, 4));
// Flux Gem - Thorns and reflection
AutoEnchantAPI.registerRule(new EnchantmentRule("flux")
.addArmorEnchantment(Enchantment.THORNS, 3)
.addArmorEnchantment(Enchantment.PROTECTION, 2));
}
}
Important Notes:
- Auto-enchants only apply while the gem is in the player's inventory
- Multiple gems can stack enchantments
- Auto-enchants won't override player's own enchantments (unless
setOverrideExisting(true)) - Removing a gem instantly removes its auto-enchants
- Uses minimal server resources with efficient 10-tick update intervals
Example: Creating a Fire Gem
Here's a complete example combining all four APIs:
import com.xoperr.core.api.protection.GemProtectionAPI;
import com.xoperr.core.api.particle.ParticleAPI;
import com.xoperr.core.api.particle.CustomParticle;
import com.xoperr.core.api.text.InventoryTextAPI;
import com.xoperr.core.api.enchant.AutoEnchantAPI;
import com.xoperr.core.api.enchant.EnchantmentRule;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.entity.Player;
public class FireGem {
// Register enchantment rules (call once in onEnable)
public static void registerFireGemEnchants() {
EnchantmentRule fireRule = new EnchantmentRule("fire")
.addArmorEnchantment(Enchantment.FIRE_PROTECTION, 4)
.addWeaponEnchantment(Enchantment.FIRE_ASPECT, 2);
AutoEnchantAPI.registerRule(fireRule);
}
public static ItemStack createFireGem() {
// Create the item
ItemStack gem = new ItemStack(Material.BLAZE_POWDER);
ItemMeta meta = gem.getItemMeta();
meta.setDisplayName("§c§lFire Gem");
meta.setCustomModelData(2001); // Your custom model
gem.setItemMeta(meta);
// Mark as protected gem (with gemId "fire" for auto-enchant matching)
GemProtectionAPI.markAsGem(gem, "fire", 1);
return gem;
}
public static void activateFireGemAbility(Player player) {
// Show activation text
InventoryTextAPI.sendTitle(player, "§cFIREBALL!", "§7Charging...", 5, 20, 5);
// Spawn flame particles around player
Location loc = player.getLocation();
for (int i = 0; i < 8; i++) {
double angle = (Math.PI * 2 / 8) * i;
double x = Math.cos(angle) * 1.5;
double z = Math.sin(angle) * 1.5;
CustomParticle flame = ParticleAPI.create("fire_burst")
.material(Material.PAPER)
.customModelData(3001)
.scale(0.5f)
.brightness(15, 0)
.spawn(loc.clone().add(x, 1, z));
// Remove particle after 2 seconds
Bukkit.getScheduler().runTaskLater(plugin, flame::remove, 40L);
}
}
}
For Plugin Developers
Adding XoperrCore as a Dependency
Maven:
<dependency>
<groupId>com.xoperr</groupId>
<artifactId>XoperrCore</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
plugin.yml:
depend: [XoperrCore]
License
Created by XoperrDev for BlissGems



