Skip to main content

Custom Items

This is a startup_scripts/ event

// Listen to item registry event
onEvent('item.registry', event => {
  
  // The texture for this item has to be placed in kubejs/assets/kubejs/textures/item/test_item.png
  // If you want a custom item model, you can create one in Blockbench and put it in kubejs/assets/kubejs/models/item/test_item.json
  event.create('test_item')
  
  // You can chain builder methods as much as you like
  event.create('test_item_2').maxStackSize(16).glow(true)
  
  // You can specify item type as 2nd argument in create(), some types have different available methods
  event.create('custom_sword', 'sword').tier('diamond').attackDamageBaseline(10.0)
})
Valid item types:
  • "basic"
    • default
  • "sword"
  • "pickaxe"
  • "axe"
  • "shovel"
  • "hoe"
  • "helmet"
  • "chestplate"
  • "leggings"
  • "boots"

Other methods item builder supports:

You can chain these methods after create()

Anything with a ??? may not be completely accurate

Physical Properties
  • maxStackSize(size)
  • unstackable()
    • Identical to maxStackSize(1)
  • maxDamage(damage)
    • ie max durability of the item
  • burnTime(ticks)
    • In a furnace
  • fireResistant(true/false)
Non-Model Visual Stuff
  • rarity('rarity')
    • Options are:
      • "common"
      • "uncommon"
      • "rare"
      • "epic"
  • glow(true/false)
  • tooltip(text...)
    • The text under the item name to provide details about it
  • color(index, colorHex)
    • If you do not have a custom model, index is 0
    • If you do have a custom model, then index is the layer hat you want to affect
    • there is an example below
  • color((item, number) => {...})
  • displayName(name)
  • name(item => {...})
    • you can put whatever code in there you want
    • must return a string
    • ???
  • translationKey(key)
    • ???
    • You don't need this unless you know what you are doing
Model Editing

There is an example below

  • textureJson(json)
    • for example {layer0:"minecraft:item/sand",layer1:"minecraft:item/paper"}
    • The contents of the texture part of item model
    • ???
  • modelJson(json)
    • the entire json that you would put for a item model, you can just put in here
    • ???
  • parentModel(modelName)
    • Set the "parent" property of this items model to modelName
  • texture(customTexturePath)
    • for example "minecraft:item/feather"
  • texture(key, customTexturePath)
    • if key is "layer0", then its the same as texture(customTexturePath)
    • ???
Bar

There an example farther below

  • barColor((item) => {...})
    • must return a color
    • any code you want
    • ???
  • barWidth(width)
    • ???
Custom Uses

The is a section below for an example

  • useAnimation(animation)
    • Can be:
      • "spear"
        • trident
      • "crossbow"
      • "eat"
        • food
      • "spyglass"
      • "block"
      • "none"
      • "bow"
      • "drink"
    • ???
  • useDuration(itemstack => {...})
    • any code you want
    • for example useDuration(itemstack => 60)
      • three seconds
    • must return a whole number
    • if you want something that does not end on its own, then use something like 72000 (an hour)
    • ???
  • use((level, player, hand) => {...})
    • for example use(() => true)
    • any code you want
    • item is usable if it is true
    • must return a boolean
    • ???
  • finishUsing((itemstack, level, entity) => {...})
    • any code you want
    • when the duration completes
    • ???
  • releaseUsing((itemstack, level, entity, tick) => {...})
    • any code you want
    • when released before the duration completes
    • ???
Miscellaneous
  • type(type)
    • for 1.16
  • tag(resourceLocation)
    • ???
  • tool(type, level)
    • for 1.16
  • modifyAttribute(attribute, identifier, d, operation)
    • ???
  • group(group_id)
    • Creative mode tab
    • Vanilla tabs are:
      • "search"
      • "buildingBlocks"
      • "decorations"
      • "redstone"
      • "transportation"
      • "misc"
      • "food"
      • "tools"
      • "combat"
      • "brewing"
  • containerItem(id)
    • A item to reference properties of
    • ???
  • subtypes(item => {...})
    • must return a itemstack collection
    • This is for making JEI or creative menu have the same item multiple times with different NBT
    • any code you want
    • ???
  • food(foodBuilder => {...})
Tool

Methods available if you use 'sword', 'pickaxe', 'axe', 'shovel' or 'hoe' type:

  • tier(toolTier)
    • Can be:
      • "wood"
      • "stone"
      • "iron"
      • "gold"
      • "diamond"
      • "netherite"
  • modifyTier(tier => ...)
    • Same syntax as custom tool tier, see below
  • attackDamageBaseline(damage)
    • You only want to modify this if you are creating a custom weapon such as Spear, Battleaxe, etc.
  • attackDamageBonus(damage)
  • speedBaseline(speed)
    • Same as attackDamageBaseline, only modify for custom weapon types
  • speed(speed)
Armor

Methods available if you use 'helmet', 'chestplate', 'leggings' or 'boots' type:

  • tier('armorTier')
    • Can be:
      • "leather"
      • "chainmail"
      • "iron"
      • "gold"
      • "diamond"
      • "turtle"
      • "netherite"
  • modifyTier(tier => ...) // Same syntax as custom armor tier, see below
Creating custom tool and armor tiers

All values are optional and by default are based on iron tier

onEvent('item.registry.tool_tiers', event => {
  event.add('tier_id', tier => {
    tier.uses = 250
    tier.speed = 6.0
    tier.attackDamageBonus = 2.0
    tier.level = 2
    tier.enchantmentValue = 14
    tier.repairIngredient = '#forge:ingots/iron'
  })
})
onEvent('item.registry.armor_tiers', event => {
  // Slot indicies are [FEET, LEGS, BODY, HEAD]
  event.add('tier_id', tier => {
    tier.durabilityMultiplier = 15 // Each slot will be multiplied with [13, 15, 16, 11]
    tier.slotProtections = [2, 5, 6, 2]
    tier.enchantmentValue = 9
    tier.equipSound = 'minecraft:item.armor.equip_iron'
    tier.repairIngredient = '#forge:ingots/iron'
    tier.toughness = 0.0 // diamond has 2.0, netherite 3.0
    tier.knockbackResistance = 0.0
  })
})

Examples:

Custom Foods

These methods are each optional, and you may include as many or as few as you like.

onEvent('item.registry', event => {
	event.create('magic_steak').food(food => {
		food
    		.hunger(6)
    		.saturation(6)//This value does not directly translate to saturation points gained
      		//The real value can be assumed to be:
      		//min(hunger * saturation * 2 + saturation, foodAmountAfterEating)
      		.effect('speed', 600, 0, 1)
      		.removeEffect('poison')
      		.alwaysEdible()//Like golden apples
      		.fastToEat()//Like dried kelp
      		.meat()//Dogs are willing to eat it
      		.eaten(ctx => {//runs code upon consumption
        		ctx.player.tell('Yummy Yummy!')
          		//If you want to modify this code then you need to restart the game.
          		//However, if you make this code call a global startup function
          		//and place the function *outside* of an 'onEvent'
          		//then you may use the command:
          		//  /kubejs reload startup_scripts
          		//to reload the function instantly.
        	})
	})
})
Custom Uses
onEvent("item.registry", event => {
event.create("nuke_soda", "basic")
        .tooltip("§5Taste of Explosion!")
        .tooltip("§c...Inappropriate intake may cause disastrous result.")
        /**
         * The use animation of the item, can be  "spear" (trident),
         * "crossbow", "eat" (food), "spyglass", "block", "none", "bow", "drink"
         * When using certain animations, corresponding sound will be played.
         */
        .useAnimation("drink")
        /**
         * The duration before the item finishs its using,
         * if you need something like hold-and-charge time (like bow),
         * consider set this to 72000 (1h) or more.
         * A returned value of 0 or lower will render the item not usable.
         */
        .useDuration((itemstack) => 64)
        /**
         * When item is about to be used.
         * If true, item will starts it use animation if duration > 0.
         */
        .use((level, player, hand) => true)
        /**
         * When the item use duration expires.
         */
        .finishUsing((itemstack, level, entity) => {
            let effects = entity.potionEffects;
            effects.add("haste", 120 * 20)
            itemstack.itemStack.shrink(1)
            if (entity.player) {
                entity.minecraftPlayer.addItem(Item.of("minecraft:glass_bottle").itemStack)
            }
            return itemstack;
        })
        /**
         * When the duration is not expired yet, but
         * players release their right button.
         * Tick is how many ticks remained for player to finish using the item.
         */
        .releaseUsing((itemstack, level, entity, tick) => {
            itemstack.itemStack.shrink(1)
            level.createExplosion(entity.x, entity.y, entity.z).explode()
        })
})
Bar
event.create("hammer")
        //Determine how long the bar is, should be an integer between 0 (empty) and 13 (full)
        //If the value is below 0, it will be treated as 0.
        //The value is capped at 13, any value over 13 will be considered "full", thus making it not shown
        .barWidth(i => i.nbt.contains("hit_count") ? i.nbt.getInt("hit_count") / 13.0 : 0)
        //Determine what color should the bar be.
        .barColor(i => Color.AQUA)
Dynamic Tinting and Model Stuff
onEvent("item.registry", (event) => {
	/**
	 * Old style with just setting color by index still works!
	 */
	event
		.create("old_color_by_index")
		.textureJson({
			layer0: "minecraft:item/paper",
			layer1: "minecraft:item/ghast_tear",
		})
		.color(0, "#70F00F")
		.color(1, "#00FFF0");

	event
		.create("cooler_sword", "sword")
		.displayName("Test Cooler Sword")
		.texture("minecraft:item/iron_sword")
		.color((itemstack) => {
			/**
			 * Example by storing the color in the nbt of the itemstack
			 * You have to return -1 to apply no tint.
			 *
			 * U can test this through: /give @p kubejs:cooler_sword{color:"#ff0000"}
			 */
			if (itemstack.nbt && itemstack.nbt.color) {
				return itemstack.nbt.color;
			}

			return -1;
		});

	event
		.create("test_item")
		.displayName("Test Item")
		.textureJson({
			layer0: "minecraft:item/beef",
			layer1: "minecraft:item/ghast_tear",
		})
		.color((itemstack, tintIndex) => {
			/**
			 * If you want to apply the color to a specific layer, you can use the tintIndex
			 * tintIndex is the texture layer index from the model: layer0 -> 0, layer1 -> 1, etc.
			 * U can use the `Color` wrapper for some default colors
			 *
			 * This example will apply the color to the ghast_tear texture.
			 */
			if (tintIndex == 1) {
				return Color.BLUE;
			}
			return -1;
		});

	/**
	 * Set a texture for a specific layer
	 */
	event.create("test_sword", "sword").displayName("Test Sword").texture("layer0", "minecraft:item/bell");

	/**
	 * Directly set your custom model json
	 */
	event.create("test_something").displayName("Test something").modelJson({
		parent: "minecraft:block/anvil",
	});
});