Custom Model Data & Item Variants
PotatoMC allows plugins to interface directly with client-side resource packs via Custom Model Data. Instead of hand-rolling raw NBT manipulation, plugins can read and write model data directly on ItemStack, and declare custom item templates using the ItemVariant & ItemVariantRegistry system.
1. Direct Custom Model Data Manipulation
Every ItemStack in PotatoMC directly exposes custom model data getters and setters:
use potato_api::types::ItemStack;
let mut item = ItemStack::new("minecraft:diamond_sword", 1);
// Set Custom Model Data
item.set_custom_model_data(Some(10501));
// Fluent builder pattern
let ruby_pick = ItemStack::new("minecraft:diamond_pickaxe", 1)
.with_custom_model_data(20042)
.with_name("§cRuby Pickaxe");
// Read Custom Model Data
if let Some(cmd) = item.custom_model_data() {
println!("Item has CustomModelData: {}", cmd);
}2. Declarative Item Variants (`ItemVariant`)
Define custom items driven by resource packs cleanly with base item, custom model data, default display names, lore, enchantments, and persistent NBT tags:
use potato_api::item_variant::ItemVariant;
let ruby_sword = ItemVariant::builder("minecraft:diamond_sword")
.custom_model_data(10501)
.name("§c§lRuby Greatsword")
.lore([
"§7Forged from crystallized nether rubies.",
"§4+14 Attack Damage",
"§6Ability: Flame Burst",
])
.enchantment("minecraft:fire_aspect", 2)
.enchantment("minecraft:unbreaking", 3)
.persistent_tag("weapon_type", "ruby_sword")
.unbreakable(true)
.build();
// Instantiate the item anytime
let stack = ruby_sword.create(1);3. Item Variant Registry (`ItemVariantRegistry`)
Manage a central catalog of custom items for your server or minigame network:
use potato_api::item_variant::ItemVariantRegistry;
let registry = ItemVariantRegistry::new();
// 1. Register variants
registry.register("mmo:ruby_sword", ruby_sword);
// 2. Create by key
if let Some(item) = registry.create("mmo:ruby_sword", 1) {
player.give_item(&item);
}
// 3. Match items against registered definitions
if registry.matches(&held_item, "mmo:ruby_sword") {
player.send_message("§aYou are holding the Ruby Greatsword!");
}
// 4. Identify any matching registered item
if let Some(variant_id) = registry.identify(&held_item) {
println!("Player held custom item: {}", variant_id);
}4. Complete RPG Item Drop Plugin Example
use potato_api::plugin::{Plugin, PluginContext, PluginMetadata};
use potato_api::item_variant::{ItemVariant, ItemVariantRegistry};
use potato_api::event::{BlockBreakEvent, Cancellable};
use potato_api::potato_plugin;
#[derive(Default)]
pub struct CustomItemPlugin;
impl Plugin for CustomItemPlugin {
fn metadata(&self) -> PluginMetadata {
PluginMetadata::new("CustomItemPlugin", "1.0.0", "Flaxa")
}
fn on_enable(&mut self, context: &mut PluginContext) -> Result<(), String> {
let registry = ItemVariantRegistry::new();
// 1. Define custom Emerald Dagger
let emerald_dagger = ItemVariant::builder("minecraft:iron_sword")
.custom_model_data(3001)
.name("§a§lEmerald Dagger")
.lore(["§7Fast attack speed, poisoned tip."])
.enchantment("minecraft:sharpness", 4)
.persistent_tag("rarity", "legendary")
.build();
registry.register("rpg:emerald_dagger", emerald_dagger);
// 2. Drop the custom dagger when breaking emerald ore
context.register_event(move |event: &mut BlockBreakEvent| {
if event.block.is_type("emerald_ore") {
event.set_drop_items(false); // Cancel vanilla drop
if let Some(dagger) = registry.create("rpg:emerald_dagger", 1) {
if let Some(player) = &event.player {
player.give_item(&dagger);
player.send_message("§a★ You found an §2Emerald Dagger§a!");
}
}
}
});
Ok(())
}
}
potato_plugin!(CustomItemPlugin);