KubeJS

This wiki is still very much work in progress! Feel free to suggest changes in #kubejs-and-code Discord channel.

Information (Read this first!)

Website and FAQ: https://kubejs.latvian.dev/

Discord server: https://discord.gg/bPFfH6P


Forge download: https://www.curseforge.com/minecraft/mc-mods/kubejs

Forge source and issue tracker: https://github.com/KubeJS-Mods/KubeJS


Fabric download: https://www.curseforge.com/minecraft/mc-mods/kubejs-fabric

Fabric source and issue tracker: https://github.com/KubeJS-Mods/KubeJS-Fabric


1.12 versions aren't supported, only 1.15 and up!


How to read Variables and Functions
Format Use Example Info
variableName

var x = event.variableName

event.variableName = 10

A simple variable, can be read and changed as well
functionName() event.functionName() Function with no parameters, can be called
functionName(int x, String y)

event.functionName(10, 'abc')

Function with parameters with types specified (even if JS doesn't have function types), can be called
variableName var x = event.variableName Variable that can only be read but can't be changed
variableName event.variableName = 10 Variable that can only be changed, but can't be read

Events

Events that get fired during game to control recipes, world, etc.

Events

List of all events

This is a list of all events. It's possible that not all events are listed here, but this list will be updated regularly.

Click on event ID to open it's class and see information, fields and methods.

ID Cancellable Type Available on Fabric
init No Startup Yes
postinit No Startup Yes
loaded No Startup Yes
command.registry No Server Startup Yes (Since 3.1)
command.run Yes Server Yes (Since 3.1)
client.init No Client Startup Yes
client.debug_info.left No Client

Yes

client.debug_info.right No Client

Yes

client.logged_in No Client Yes (Since 3.1)
client.logged_out No Client Yes (Since 3.1)
client.tick No Client Yes
client.item_tooltip No Client Yes
server.load No Server Startup Yes (Since 3.1)
server.unload No Server Yes (Since 3.1)
server.tick No Server Yes
server.datapack.first No Server Startup Yes
server.datapack.last No Server Startup Yes
recipes No Server Startup Yes
world.load No Server Yes
world.unload No Server Yes
world.tick No Server Yes
world.explosion.pre Yes Server Yes (Since 3.1)
world.explosion.post No Server Yes (Since 3.1)
player.logged_in No Server Yes (Since 3.1)
player.logged_out No Server Yes (Since 3.1)
player.tick No Server Yes (Since 3.1)
player.data_from_server. Yes Client Yes (Since 3.1)
player.data_from_client. Yes Server Yes (Since 3.1)
player.chat Yes Server Yes (Since 3.1)
player.advancement No Server Yes (Since 3.1)
player.inventory.opened No Server Yes (Since 3.1)
player.inventory.closed No Server Yes (Since 3.1)
player.inventory.changed No Server Yes (Since 3.1)
player.chest.opened No Server Yes (Since 3.1)
player.chest.closed No Server Yes (Since 3.1)
entity.death Yes Server Yes (Since 3.1)
entity.attack Yes Server Yes (Since 3.1)
entity.drops Yes Server No
entity.check_spawn Yes Server No
entity.spawned Yes Server Yes (Since 3.1)
block.registry No Startup Yes
block.missing_mappings No Server Startup No
block.tags No Server Startup Yes
block.right_click Yes Server Yes
block.left_click Yes Server Yes
block.place Yes Server Yes (Since 3.1)
block.break Yes Server Yes (Since 3.1)
block.drops No Server No
item.registry No Startup Yes
item.missing_mappings No Server Startup No
item.tags No Server Startup Yes
item.right_click Yes Server Yes
item.right_click_empty No Server Yes
item.left_click No Server Yes
item.entity_interact Yes Server Yes (Since 3.1)
item.pickup Yes Server Yes
item.toss Yes Server Yes
item.crafted No Server Yes (Since 3.1)
item.smelted No Server Yes
fluid.tags No Server Startup Yes
entity_type.tags No Server Yes

 

Events

EventJS

This event is the most basic event class, parent of all other events.

Parent class

Object

Can be cancelled

No

Variables and Functions

Name Return Type Info
cancel() void Cancels event. If the event can't be cancelled, it won't do anything.
Events

CommandEventJS

This event needs cleanup! Using it is not recommended.

Information

This event is fired when a command is executed on server side.

Parent class

EventJS

Can be cancelled

Yes

Variables and Functions

Name Type Info
parseResults ParseResults<CommandSource> Command params 
exception Exception Error, set if something went wrong



Events

TagEventJS

This event is fired when a tag collection is loaded, to modify it with script. You can add and remove tags for items, blocks, fluids and entity types.

Parent class

EventJS

Can be cancelled

No

Variables and Functions

Name Type Info
type String Tag collection type.
get(String tag) TagWrapper Returns specific tag container which you can use to add or remove objects to. tag parameter can be something like 'forge:ingots/copper'. If tag doesn't exist, it will create a new one.

TagWrapper class

Variables and Functions

Name Type Info
add(String id) TagWrapper (itself) Adds an object to this tag. If string starts with # then it will add all objects from the second tag.
remove(String id) TagWrapper (itself) Removes an object from tag, works the same as add().

Examples

// Listen to item tag event
events.listen('item.tags', event => {
  // Get the #forge:cobblestone tag collection and add Diamond Ore to it
  event.get('forge:cobblestone').add('minecraft:diamond_ore')
  
  // Get the #forge:cobblestone tag collection and remove Mossy Cobblestone from it
  event.get('forge:cobblestone').remove('minecraft:mossy_cobblestone')
})

Recipes use item tags, not block or fluid tags, even if items representing those are blocks. Like minecraft:cobblestone even if it's a block, it will still be an item tag for recipes.

Events

RecipeEventJS

Examples

// kubejs/server_scripts/example.js
// This is just an example script to show off multiple types of recipes and removal methods
// Supports /reload

// Enable recipe logging, off by default
settings.logAddedRecipes = true
settings.logRemovedRecipes = true
// Enable skipped recipe logging, on by default
settings.logSkippedRecipes = false

// Listen to server recipe event
events.listen('recipes', event => {
  // Remove broken recipes from vanilla and other mods
  // This is on by default, so you don't need this line
  //event.removeBrokenRecipes = true

  event.remove({}) // Deletes all recipes
  event.remove({id: 'minecraft:glowstone'}) // Removes data/minecraft/recipes/glowstone.json
  event.remove({input: '#forge:dusts/redstone'}) // Removes all recipes where input is Redstone Dust tag
  event.remove({output: '#minecraft:wool'}) // Removes all recipes where output is Wool tag
  event.remove({mod: 'quartzchests'}) // Remove all recipes from Quartz Chests mod
  event.remove({type: 'minecraft:campfire_cooking'}) // Remove all campfire cooking recipes

  // Add shaped recipe for 3 Stone from 8 Sponge in chest shape
  // (Shortcut for event.recipes.minecraft.crafting_shaped)
  event.shaped(item.of('minecraft:stone', 3), [
    'SSS',
    'S S',
    'SSS'
  ], {
    S: 'minecraft:sponge'
  })

  // Add shapeless recipe for 4 Cobblestone from 1 Stone and 1 Glowstone
  // (Shortcut for event.recipes.minecraft.crafting_shapeless)
  event.shapeless(item.of('minecraft:cobblestone', 4), ['minecraft:stone', '#forge:dusts/glowstone'])

  // Add Stonecutter recipe for Golden Apple to 4 Apples
  event.recipes.minecraft.stonecutting(item.of('minecraft:apple', 4), 'minecraft:golden_apple')
  // Add Stonecutter recipe for Golden Apple to 2 Carrots
  event.recipes.minecraft.stonecutting(item.of('minecraft:carrot', 2), 'minecraft:golden_apple')

  // Add Furnace recipe for Golden Apple to 3 Carrots
  // (Shortcut for event.recipes.minecraft.smelting)
  event.smelting(item.of('minecraft:carrot', 2), 'minecraft:golden_apple')

  // Add similar recipes for Blast Furnace, Smoker and Campfire
  event.recipes.minecraft.blasting(item.of('minecraft:apple', 3), 'minecraft:golden_apple')
  event.recipes.minecraft.smoking(item.of('minecraft:apple', 5), 'minecraft:golden_apple')
  event.recipes.minecraft.campfire_cooking('minecraft:apple', 'minecraft:golden_apple')
  // You can also add .xp(1.0) at end of any smelting recipe to change given XP

  // Create a variable for function and use that to make things shorter
  var s = event.recipes.minecraft.smelting
  s('minecraft:blue_dye', '#forge:gems/lapis')
  s('minecraft:black_dye', 'minecraft:ink_sac')
  s('minecraft:white_dye', 'minecraft:bone_meal')

  // Add Create's crushing recipe, Apple to Apple + 50% Carrot
  event.recipes.create.crushing(['minecraft:apple', item.of('minecraft:carrot').chance(0.5)], 'minecraft:apple', 100)

  // If you use {} as only argument, it will be using vanilla Json syntax
  // You can add recipe to any recipe handler that uses vanilla recipe system or isn't supported by KubeJS
  event.recipes.create.crushing({
    ingredients: [
      ingredient.of('minecraft:carrot').toJson()
    ],
    results: [
      item.of('minecraft:apple').chance(0.5).toResultJson(),
      item.of('minecraft:carrot').toResultJson()
    ],
    processingTime: 100
  })
  
  // In all shapeless crafting recipes, replace any planks with Gold Nugget in input items
  event.replaceInput({type: 'minecraft:crafting_shapeless'}, '#minecraft:planks', 'minecraft:gold_nugget')
  
  // In all recipes, replace Stick with Oak Sapling in output items 
  event.replaceOutput({}, 'minecraft:stick', 'minecraft:oak_sapling')
})

Classes

Available fields and methods and examples on how to use them

Classes

Object

Parent class of all Java objects. 

Parent

None (and itself at the same time, don't question it)

Variables and Functions

Name Type Info
toString() String Tag collection type.
equals(Object other) boolean Checks equality with another object.
hashCode() int Hash code of this object. It is used to optimize maps and other things, should never be used for object equality.
class Class Object's type/class.
Classes

String

Class of string objects, such as "abc" (and in JS 'abc' works as well) 

Parent

Object

Variables and Functions

Name Type Info
empty boolean Returns if string is empty a.k.a string === ''
toLowerCase() String Returns a copy of this string, but with all characters in upper case
toUpperCase() String Returns a copy of this string, but with all characters in lower case
equalsIgnoseCase(String other) boolean Hash code of this object. It is used to optimize maps and other things, should never be used for object equality.
length() int Number of characters
charAt(int index) char Single character at index
Classes

Primitive Types

Information

Primitive types are objects that don't have a real class and don't inherit methods from Object.

All primitive types

Type Java class Info
void Void No type
byte Byte 8 bit decimal number.
short Short 16 bit decimal number.
int Integer 32 bit decimal number, most common decimal type.
long Long 64 bit decimal number.
float Float 32 bit floating point number.
double Double 64 bit floating point number.
char Character Single character in String such as 'a' or '-'.
boolean Boolean Only true and false values. Can be checked in if function without comparing to true, as if (x) or if (!x) instead of if (x == true) or if (x == false).

Global

Constants, classes and functions

Examples

Example scripts for various things you can do with KubeJS

Examples

Recipes

Moved to RecipeEventJS!

Examples

Custom Blocks

This is a startup script.

events.listen('block.registry', function (event) {
  event.create('test_block').material('glass').hardness(0.5).displayName('Test Block')
})


The texture for this block has to be placed in kubejs/assets/kubejs/textures/block/test_block.png.
If you want a custom block model, you can create one in Blockbench and put it in kubejs/assets/kubejs/models/block/test_block.json.

 

List of available materials - to change break/walk sounds and to change some properties (tool used to mine, etc):

Material
air
wood
rock
iron
organic

earth

water
lava
leaves
plants
sponge
wool
sand
glass
tnt
coral
ice
snow
clay
groud
dragon_egg
portal
cake
web
slime
honey
berry_bush
lantern
Examples

Reflection

Very limited reflection is possible, but is not recommended. Use it in cases, when mod doesn't have integration.

// side: client
// This is a startup script. This script changes a java variable in ProjectE mod by accessing code directly

// Listen to post-init event, after all mods have loaded
events.listen('postinit', function (event) {
  // Loads Java class field
  var devEnvField = utils.field('moze_intel.projecte.PECore', 'DEV_ENVIRONMENT')
  // Changes public static boolean DEV_ENVIRONMENT of PECore class to false
  devEnvField.staticSet(false)
})
Examples

Chat Event

This script is peak of human evolution. Whenever someone says "Creeper" in chat, it replies with "Aw man".

events.listen('player.chat', function (event) {
  // Check if message equals creeper, ignoring case
  if (event.message.trim().equalsIgnoreCase('creeper')) {
    // Schedule task in 1 tick, because if you reply immidiently, it will print before player's message
    event.server.scheduleInTicks(1, event.server, function (callback) {
      // Tell everyone Aw man, colored green. Callback data is the server
      callback.data.tell(text.green('Aw man'))
    })
  }
})

Another example, cancelling the chat event. No need to schedule anything now, because player's message wont be printed,

events.listen('player.chat', function (event) {
  // Check if message equals creeper, ignoring case
  if (event.message.startsWith('!some_command')) {
    event.player.tell('Hi!')
    event.cancel()
  }
})
Examples

Network Packets

This script shows how to use network packets:

// Listen to a player event, in this case item right-click
events.listen('item.right_click', function (event) {
  // Check if item was right-clicked on client or server side
  if (event.player.isServer()) {
    // Send data {test: 123} to channel "test_channel_1". Channel ID can be any string, but it's recommended to keep it to snake_case [a-z_0-9].
    // Receiving side will either be client (because its fired from server).
    event.player.sendData('test_channel_1', {
      test: 123
    })
  } else {
    // It's not required to use a different channel ID, but it's recommended.
    // Receiving side will either be server (because its fired from client).
    event.player.sendData('test_channel_2', {
      test: 456
    })
  }
})

// Listen to event that gets fired when network packet is received from server.
events.listen('player.data_from_server.test_channel_1', function (event) {
  log.info(event.data.get('test').asInt()) // Prints 123
})

// Listen to event that gets fired when network packet is received from client.
events.listen('player.data_from_client.test_channel_2', function (event) {
  log.info(event.data.get('test').asInt()) // Prints 456
})
Examples

Starting Items

This script adds items on first time player joins, checking gamestages

Requires GameStages mod!

// Listen to player login event
events.listen('player.logged_in', function (event) {
  // Check if player doesn't have "starting_items" gamestage yet
  if (!event.hasGameStage('starting_items')) {
    // Add the gamestage
    event.addGameStage('starting_items')
    // Give some items to player
    event.player.give('minecraft:stone_sword')
    event.player.give({ item: 'minecraft:stone_pickaxe', data: 10 })
    event.player.give({ item: 'minecraft:apple', count: 30 })
  }
})
Examples

Custom Items

// Listen to block registry event
events.listen('item.registry', function (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').displayName('Test Item')
})
Examples

FTB Utilities Rank Promotions

With this script you can have FTB Utilities roles that change over time.

Is for 1.12 only. Requires FTB Utilities.

events.listen('player.tick', function (event) {
  // This check happens every 20 ticks, a.k.a every second
  if (event.player.server && event.player.ticksExisted % 20 === 0) {
    var rank = event.player.data.ftbutilities.rank
    events.post('test_event', {testValue: rank.id})
    var newRank = ftbutilities.getRank(rank.getPermission('promotion.next'))

    if (newRank) {
      var timePlayed = event.player.stats.get('stat.playOneMinute') / 20 // Seconds player has been on server
      var timeRequired = newRank.getPermissionValue('promotion.timer').getInt()

      if (timeRequired > 0 && timePlayed >= timeRequired && rank.addParent(newRank)) {
        if (!events.postCancellable('ftbutilities.rank.promoted.' + newRank.id, {'player': event.player, 'rank': newRank})) {
          event.player.tell('You have been promoted to ' + newRank.getPermission('promotion.name') + '!')
        }
        ftbutilities.saveRanks()
      }
    }
  }
})

// When player gets promoted to 'trusted' rank, give them gold ingot (uncomment the line)
events.listen('ftbutilities.rank.promoted.trusted', function (event) {
  // event.data.player.give('minecraft:gold_ingot')
})

3 example roles in ranks.txt:

[player]
power: 1
default_player_rank: true
promotion.name: Player
promotion.next: newcomer
promotion.timer: 5
command.ftbutilities.rtp: false
command.ftbutilities.home: false

[newcomer]
power: 5
promotion.name: Newcomer
promotion.next: regular
promotion.timer: 15
ftbutilities.chat.name_format: <&aNewcomer &r{name}>
command.ftbutilities.rtp: true

[regular]
power: 10
promotion.name: Regular
promotion.next: trusted
promotion.timer: 30
ftbutilities.chat.name_format: <&9Regular &r{name}>
command.ftbutilities.home: true

After 5 seconds of play time, player will be promoted to newcomer.
After 15 seconds (or 10 since previous role) they will be promoted to regular.
After 30 seconds (or 15 since previous role) they will be promoted to trusted, etc.

Examples

Clearlag

This script removes all items from world every 30 minutes. Only works in 1.12.

// Create item whitelist filter that won't be deleted with clearlag
var whitelist = ingredient.matchAny([
  'minecraft:diamond', // Adds diamond to whitelist
  'minecraft:gold_ingot',
  ingredient.mod('tinkersconstruct'), // Adds all items from tinkerscontruct to whitelist
  'minecraft:emerald'
])

// Create variable for last clearlag result
var lastClearLagResult = utils.newList()
// Create variable for total number of items
var lastTotalClearLagResult = utils.newCountingMap()

// Create new function that clears lag
function clearLag (server) {
  // Get a list of all entities on server with filter that only returns items
  var itemList = server.getEntities('@e[type=item]')
  // Create new local map for item counters
  var lastResult = utils.newCountingMap()
  // Clear old result lists
  lastClearLagResult.clear()
  lastTotalClearLagResult.clear()
  // Iterate over each entity in itemList and add item counters
  itemList.forEach(function (entity) {
    if (!whitelist.test(entity.item)) {
      // Get the name of item
      var key = entity.item.name
      // Add to entity count
      lastResult.add(key, 1)
      // Add to total item count
      lastTotalClearLagResult.add(key, entity.item.count)
      // Kill the item entity
      entity.kill()
    }
  })

  // Update and sort last result list
  lastClearLagResult.addAll(lastResult.entries)
  lastClearLagResult.sort(null)

  // Tell everyone how many items will be removed
  server.tell([
    text.lightPurple('[ClearLag]'),
    ' Removed ',
    lastTotalClearLagResult.totalCount,
    ' items. ',
    text.yellow('Click here').click('command:/clearlagresults'),
    ' for results.'
  ])
}

// Listen for server load event
events.listen('server.load', function (event) {
  // Log message in console
  event.server.tell([ text.lightPurple('[ClearLag]'), ' Timer started, clearing lag in 30 minutes!' ])
  // Schedule new task in 30 minutes
  event.server.schedule(MINUTE * 30, event.server, function (callback) {
    // Tell everyone on server that items will be removed
    callback.data.tell([ text.lightPurple('[ClearLag]'), ' Removing all items on ground in one minute!' ])
    // Schedule a subtask that will clear items in one minute
    callback.data.schedule(MINUTE, callback.data, function (callback2) {
      clearLag(callback2.data)
    })
    // Re-schedule this task for another 30 minutes (endless loop)
    callback.reschedule()
  })
})

// Register commands
events.listen('command.registry', function (event) {
  // Register new OP command /clearlag, that instantly runs clearlag
  event
    .create('clearlag')
    .op()
    .execute(function (sender, args) {
      clearLag(sender.server)
    })
    .add()

  // Register new non-OP command /clearlagresults, that displays stats of all removed items from previous /clearlag
  event
    .create('clearlagresults')
    .execute(function (sender, args) {
      sender.tell([ text.lightPurple('[ClearLag]'), ' Last clearlag results:' ])

      lastClearLagResult.forEach(function (entry) {
        var total = lastTotalClearLagResult.get(entry.key)

        if (entry.value == total) {
          sender.tell([ text.gold(entry.key), ': ', text.red(entry.value) ])
        } else {
          sender.tell([ text.gold(entry.key), ': ', text.red(entry.value), ' entities, ', text.red(total), ' total' ])
        }
      })
    })
    .add()
})
Examples

Scheduled Server Events

At server load, you can schedule anything to happen at later time. Within callback handler you can also call callback.reschedule() to repeat this event after initial timer or callback.reschedule(newTime) to change it.

Whatever you pass as 2nd argument will be returned in callback as data.

The example script restarts server after 2 hours but notifies players 5 minutes before that.

events.listen('server.load', function (event) {
  event.server.schedule(115 * MINUTE, event.server, function (callback) {
    callback.data.tell('Server restarting in 5 minutes!')
  })
  
  event.server.schedule(120 * MINUTE, event.server, function (callback) {
    callback.data.runCommand('/stop')
  })
})
Examples

FTB Quests Integration

events.listen('ftbquests.custom_task.75381f79', function (event) {
  log.info('Custom task!')
  event.checkTimer = 20
  event.check = function (task, player) {
    if (player.world.daytime && player.world.raining) {
      task.progress++
    }
  }
})

events.listen('ftbquests.custom_reward.e4f76908', function (event) {
  log.info('Custom reward!')
  event.player.tell('Hello!')
})

events.listen('ftbquests.completed.abc', function (event) {
  event.notifiedPlayers.tell('Custom task completed!')
})

events.listen('ftbquests.completed.ding', function (event) {
  event.onlineMembers.playSound('entity.experience_orb.pickup')
})

events.listen('entity.death', function (event) {
  if(event.server
  && event.source.actual
  && event.source.actual.player
  && event.source.actual.mainHandItem.id.equals('minecraft:wooden_sword')
  && event.entity.type.equals('minecraft:zombie')) {
    event.source.actual.data.ftbquests.addProgress('12345678', 1)
  }
})
Examples

JEI Integration

Sub-types

events.listen('jei.subtypes', function (event) {
  event.useNBT('example:item')
  event.userNBTKey('example:item', 'type')
})

Hide Items & Fluids

events.listen('jei.hide.items', function (event) {
  event.hide('example:ingredient')
})

events.listen('jei.hide.fluids', function (event) {
  event.hide('example:fluid')
})

Add Items & Fluids

events.listen('jei.add.items', function (event) {
  event.add(item.of('example:item').nbt({test: 123}))
})

events.listen('jei.add.fluids', function (event) {
  event.add('example:fluid')
})

Add Information

events.listen('jei.information', function (event) {
  event.add('example:ingredient', ['Line 1', 'Line 2'])
})
Examples

REI Integration (Fabric Only)

Hide Items

events.listen('rei.hide.items', function (event) {
  event.hide('example:ingredient')
})

Add Items

events.listen('rei.add.items', function (event) {
  event.add(item.of('example:item').nbt({test: 123}))
})

Add Information

events.listen('rei.information', function (event) {
  event.add('example:ingredient', 'Title', ['Line 1', 'Line 2'])
})