100% found this document useful (1 vote)
4K views75 pages

Kubejs

This event allows modifying tags for items, blocks, fluids and entities when a tag collection loads. Tags can be added or removed from collections for items, blocks, fluids, and entity types.

Uploaded by

roman sch
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
4K views75 pages

Kubejs

This event allows modifying tags for items, blocks, fluids and entities when a tag collection loads. Tags can be added or removed from collections for items, blocks, fluids, and entity types.

Uploaded by

roman sch
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 75

KubeJS

This wiki is still very much work in progress! Feel free to suggest changes in the #off-topic Discord

channel.

Intro

Events

List of all events

EventJS

CommandEventJS

TagEventJS

RecipeEventJS

WorldgenAddEventJS

WorldgenRemoveEventJS

ItemTooltipEventJS

Classes

Object

String

Primitive Types

Global

Examples

KubeJS UI

Custom Items

Custom Blocks

Loot Table Modification

Item Modification

Block Modification

JEI Integration

REI Integration

FTB Quests Integration

Reflection / Java access


Painter API

Units

Chat Event

Network Packets

Starting Items

FTB Utilities Rank Promotions

Clearlag 1.12

Scheduled Server Events

Changing Window Title and Icon

Custom Fluids
Intro
FAQ
What does this mod do?

This mod lets you create scripts in JavaScript language to manage your server, add new blocks

and items, change recipes, add custom handlers for quest mods and more!

How to use it?

Run the game with mod installed once. It should generate  kubejs  folder in your minecraft

directory with example scripts and README.txt. Read that!

I don't know JavaScript

There's examples and pre-made scripts here. And you can always ask in discord support channel

for help with scripts, but be specific.

Can I reload scripts?

Yes, use  /reload  to reload  server_scripts/ ,  F3 + T  to reload  client_scripts/  and 

/kubejs reload startup_scripts  to reload  startup_scripts/ . If you don't care about reloading

recipes but are testing some world interaction event, you can run /kubejs reload server_scripts .

Note: Not everything is reloadable. Some things require you to restart game, some only world,

some work on fly. Reloading startup scripts is not recommended, but if you only have event

listeners, it shouldn't be a problem.

What mod recipes does it support / is mod X supported?


If the mod uses datapack recipes, then it's supported by default. Some more complicated mods

require addon mods, but in theory, still would work with datapack recipes. See Recipes section for

more info.

What features does this mod have?

The feature list would go here if I actually wrote it. But basically, editing and creating recipes, tags,

items, blocks, fluids, worldgen. Listening to chat, block placement, etc. events. Just look at the

event list on Wiki.

How does this mod work?

It uses a fork of Rhino, a JavaScript engine by Mozilla to convert JS code to Java classes at runtime.

KubeJS wraps minecraft classes and adds utilities to simplify that a lot and remove need for

mappings. Architectury lets nearly the same source code be compiled for both Forge and Fabric

making porting extremely easy.

Ok, but what if it.. doesn't work?

You can report issues here.

I have more questions/suggestions!

If wiki didn't have the answer for what you were looking for, you can join the Discord server and

ask for help on #support channel!

Image not found or type unknown

Website: https://kubejs.com/

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


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

Anything below 1.16 is no longer supported!

 
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.

Type descriptions:

Startup: Scripts go in kubejs/startup_scripts folder. 

Server: Scripts go in kubejs/server_scripts folder. Will be reloaded when you run /reload

command.

Server Startup: Same as Server, and the event will be fired at least once when server loads.

Client: Scripts go in kubejs/client_scripts folder. Currently only reloaded if you have KubeJS

UI installed in you run Ctrl+F5 in a menu.

Client Startup: Same as Client, and the event will be fired at least once when client loads.

ID Cancellable Type

init No Startup

postinit No Startup

loaded No Startup

command.registryNo Server

command.run Yes Server

client.init No Client

client.debug_info.left
No Client

client.debug_info.right
No Client
ID Cancellable Type

client.logged_in No Client

client.logged_out No Client

client.tick No Client

server.load No Server

server.unload No Server

server.tick No Server

server.datapack.first
No Server

server.datapack.last
No Server

recipes No Server

world.load No Server

world.unload No Server

world.tick No Server

world.explosion.pre
Yes Server

world.explosion.post
No Server

player.logged_in No Server

player.logged_outNo Server

player.tick No Server

player.data_from_server.
Yes Client

player.data_from_client.
Yes Server

player.chat Yes Server

player.advancement
No Server

player.inventory.opened
No Server
ID Cancellable Type

player.inventory.closed
No Server

player.inventory.changed
No Server

player.chest.opened
No Server

player.chest.closed
No Server

entity.death Yes Server

entity.attack Yes Server

entity.drops Yes Server

entity.check_spawn
Yes Server

entity.spawned Yes Server

block.registry No Startup

block.missing_mappings
No Server

block.tags No Server

block.right_click Yes Server

block.left_click Yes Server

block.place Yes Server

block.break Yes Server

block.drops No Server

item.registry No Startup

item.missing_mappings
No Server

item.tags No Server

item.right_click Yes Server

item.right_click_empty
No Server
ID Cancellable Type

item.left_click No Server

item.entity_interact
Yes Server

item.modificationNo Startup

item.pickup Yes Server

item.tooltip No Client

item.toss Yes Server

item.crafted No Server

item.smelted No Server

fluid.registry No Startup

fluid.tags No Server

entity_type.tags No Server

worldgen.add No Startup

worldgen.removeNo Startup

 
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

Cancels event. If the event can't


cancel() void 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 Command params 
<CommandSource>

Error, set if something went


exception Exception
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.

Returns specific tag container which you can use to


add or remove objects to. tag parameter can be
get(String tag) TagWrapper
something like 'forge:ingots/copper'. If tag doesn't
exist, it will create a new one.

add(String tag, String


TagWrapperShortcut method for event.get(tag).add(ids).
[]/Regex ids)

remove(String tag, String


TagWrapperShortcut method for event.get(tag).remove(ids).
[]/Regex ids)

removeAll(String tag) TagWrapperShortcut method for event.get(tag).removeAll().

removeAllTagsFrom(String[]
void Removes all tags from object
ids)
TagWrapper class

Variables and Functions

Name Type Info

Adds an object to this tag. If string starts with # then it


add(String[]/Regex TagWrapper
will add all objects from the second tag. It can be either
ids) (itself)
single string, regex (/regex/flags) or array of either.

remove(String TagWrapper
Removes an object from tag, works the same as add().
[]/Regex ids) (itself)

TagWrapper
removeAll() Removes all entries from tag.
(itself)

Examples
// Listen to item tag event

onEvent('tags.items', event => { // Get the #forge:cobblestone tag collection and add

Diamond Ore to it

event.add('forge:cobblestone', 'minecraft:diamond_ore')

// Get the #forge:cobblestone tag collection and remove Mossy Cobblestone from it

event.remove('forge:cobblestone', 'minecraft:mossy_cobblestone')

// Get #forge:ingots/copper tag and remove all entries from it

event.removeAll('forge:ingots/copper')

// Required for FTB Quests to check item NBT event.add('itemfilters:check_nbt',

'some_item:that_has_nbt_types')

// You can create new tags the same way you add to existing, just give it a name

event.add('forge:completely_new_tag', 'minecraft:clay_ball')

// Removes all tags from this entry

event.removeAllTagsFrom('minecraft:stick')})

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.

tags.blocks is for adding tags to block types, it works the same way. You can find existing

block tags if you look at a block with F3 mode enabled, on side. These are mostly only used

for technical reasons, and like mentioned above, if its for recipes/inventory, you will want to

use tags.items even for blocks.


Events

RecipeEventJS
Examples

The most basic script to add a single recipe:

onEvent('recipes', event => {

event.shaped('3x minecraft:stone', [

'SAS',

'S S',

'SAS'

], {

S: 'minecraft:sponge',

A: 'minecraft:apple'

})})

The most basic script to remove a recipe:

onEvent('recipes', event => {

event.remove({output: 'minecraft:stick'})})

Example recipe script:

// kubejs/server_scripts/example.js// This is just an example script to show off multiple

types of recipes and removal methods

// Supports /reload

// Listen to server recipe event

onEvent('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({}) // Removes all recipes (nuke option, usually not recommended)

event.remove({output: 'minecraft:stone_pickaxe'}) // Removes all recipes where output is


stone pickaxe event.remove({output: '#minecraft:wool'}) // Removes all recipes where output

is Wool tag event.remove({input: '#forge:dusts/redstone'}) // Removes all recipes where

input is Redstone Dust tag event.remove({mod: 'quartzchests'}) // Remove all recipes from

Quartz Chests mod event.remove({type: 'minecraft:campfire_cooking'}) // Remove all campfire

cooking recipes event.remove({id: 'minecraft:glowstone'}) // Removes recipe by ID. in this

case, data/minecraft/recipes/glowstone.json event.remove({output:

'minecraft:cooked_chicken', type: 'minecraft:campfire_cooking'}) // You can combine filters,

to create ANDk logic

// You can use 'mod:id' syntax for 1 sized items. For 2+ you need to use '2x mod:id' or

Item.of('mod:id', count) syntax. If you want NBT or chance, 2nd is required

// Add shaped recipe for 3 Stone from 8 Sponge in chest shape // (Shortcut for

event.recipes.minecraft.crafting_shaped) // If you want to use Extended Crafting, replace

event.shapeless with event.recipes.extendedcrafting.shapeless_table event.shaped('3x

minecraft:stone', [

'SAS',

'S S',

'SAS'

], {

S: 'minecraft:sponge',

A: 'minecraft:apple'

})

// Add shapeless recipe for 4 Cobblestone from 1 Stone and 1 Glowstone // (Shortcut for

event.recipes.minecraft.crafting_shapeless) // If you want to use Extended Crafting, replace

event.shapeless with event.recipes.extendedcrafting.shaped_table event.shapeless('4x

minecraft:cobblestone', ['minecraft:stone', '#forge:dusts/glowstone'])

// Add Stonecutter recipe for Golden Apple to 4 Apples event.stonecutting('4x

minecraft:apple', 'minecraft:golden_apple') // Add Stonecutter recipe for Golden Apple to 2

Carrots

event.stonecutting('2x minecraft:carrot', 'minecraft:golden_apple')

// Add Furnace recipe for Golden Apple to 3 Carrots // (Shortcut for

event.recipes.minecraft.smelting) event.smelting('2x minecraft:carrot',

'minecraft:golden_apple') // Similar recipe to above but this time it has a custom, static

ID - normally IDs are auto-generated and will change. Useful for Patchouli

event.smelting('minecraft:golden_apple', 'minecraft:carrot').id('mymodpack:my_recipe_id')

// Add similar recipes for Blast Furnace, Smoker and Campfire event.blasting('3x

minecraft:apple', 'minecraft:golden_apple') event.smoking('5x minecraft:apple',

'minecraft:golden_apple') event.campfireCooking('8x minecraft:apple',

'minecraft:golden_apple') // You can also add .xp(1.0) at end of any smelting recipe to

change given XP
// Add a smithing recipe that combines 2 items into one (in this case apple and gold

ingot into golden apple) event.smithing('minecraft:golden_apple', 'minecraft:apple',

'minecraft:gold_ingot')

// Create a function and use that to make things shorter. You can combine multiple actions

let multiSmelt = (output, input, includeBlasting) => { event.smelting(output,

input)

if (includeBlasting) {

event.blasting(output, input)

multiSmelt('minecraft:blue_dye', '#forge:gems/lapis', true)

multiSmelt('minecraft:black_dye', 'minecraft:ink_sac', true)

multiSmelt('minecraft:white_dye', 'minecraft:bone_meal', false)

// If you use custom({json}) it will be using vanilla Json/datapack syntax. Must include

"type": "mod:recipe_id"! // You can add recipe to any recipe handler that uses vanilla

recipe system or isn't supported by KubeJS // You can copy-paste the json directly, but you

can also make more javascript-y by removing quotation marks from keys // You can replace

{item: 'x', count: 4} in result fields with Item.of('x', 4).toResultJson() // You can

replace {item: 'x'} / {tag: 'x'} with Ingredient.of('x').toJson() or

Ingredient.of('#x').toJson() // In this case, add Create's crushing recipe, Oak Sapling to

Apple + 50% Carrot

// Important! Create has integration already, so you don't need to use this. This is just

an example for datapack recipes!

event.custom({

type: 'create:crushing',

ingredients: [

Ingredient.of('minecraft:oak_sapling').toJson()

],

results: [

Item.of('minecraft:apple').toResultJson(),

Item.of('minecraft:carrot').withChance(0.5).toResultJson()

],

processingTime: 100

})

// Example of using items with NBT in a recipe

event.shaped('minecraft:book', [
'CCC',

'WGL',

'CCC'

], {

C: '#forge:cobblestone', // Item.of('id', {key: value}), it's recommended to use

/kubejs hand L: Item.of('minecraft:enchanted_book',

{StoredEnchantments:[{lvl:1,id:"minecraft:sweeping"}]}), // Same principle, but if its an

enchantment, there's a helper method W:

Item.of('minecraft:enchanted_book').enchant('minecraft:respiration', 2), G:

'#forge:glass'

})

// 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')})

Possible settings you can change for recipes. It's recommended that you put this in it's own server

scripts file, like  settings.js

// priority: 5

// Enable recipe logging, off by defaultsettings.logAddedRecipes = true

settings.logRemovedRecipes = true// Enable skipped recipe logging, off by default

settings.logSkippedRecipes = true// Enable erroring recipe logging, on by default,

recommended to be kept to truesettings.logErroringRecipes = false

As mentioned before, you can add any recipe from any mod with JSON syntax (see

event.custom({}) ) but these mods are supported as addons with special syntax:

KubeJS Mekanism

KubeJS Immersive Engineering

KubeJS Thermal

KubeJS Blood Magic

KubeJS Create
Poorly documented things below!

You can transform ingredients in shaped and shapeless recipes by adding these functions at end

of it:

.damageIngredient(IngredientFilter filter, int damage?) // Will damage item when you craft

with it

.replaceIngredient(IngredientFilter filter, ItemStackJS item) // Will replace item with another

(like bucket)

.keepIngredient(IngredientFilter filter) // Will keep item without doing anything to it

.customIngredientAction(IngredientFilter filter, String customId) // Custom action that has to

be registered in startup script

IngredientFilter can be either

ItemStackJS ('minecraft:dirt', Item.of('minecraft:diamond_sword').ignoreNBT(), etc)

Integer index of item in crafting table (0, 1, etc)

Object with item and/or index ( {item: 'something', index: 0}, etc) 

Examples:

onEvent('recipes', event => { event.shapeless('9x minecraft:melon_slice', [ // Craft 9

watermelon slices Item.of('minecraft:diamond_sword').ignoreNBT(), // Diamond sword that

ignores damage

'minecraft:minecraft:melon' // Watermelon block

]).damageItem(Item.of('minecraft:diamond_sword').ignoreNBT()) // Damage the sword (also has

to ignore damage or only 0 damage will work)

// Craft example block from 2 diamond swords and 2 dirt. After crafting first diamond

sword is damaged (index 0) and 2nd sword is kept without changes.

event.shaped('kubejs:example_block', [

'SD ',

'D S'

], {

S: Item.of('minecraft:diamond_sword').ignoreNBT(),

D: 'minecraft:dirt'

}).damageIngredient(0).keepIngredient('minecraft:diamond_sword')
// Craft example block from 2 diamond swords and 2 stones. After crafting, diamond sword

is replaced with stone sword

event.shapeless('kubejs:example_block', [

Item.of('minecraft:diamond_sword').ignoreNBT(),

'minecraft:stone',

Item.of('minecraft:diamond_sword').ignoreNBT(),

'minecraft:stone'

]).replaceIngredient('minecraft:diamond_sword', 'minecraft:stone_sword')

// Craft clay from sand, bone meal, dirt and water bottle. After crafting, glass bottle

is left in place of water bottle

event.shapeless('minecraft:clay', [

'minecraft:sand',

'minecraft:bone_meal',

'minecraft:dirt',

Item.of('minecraft:potion', {Potion: "minecraft:water"})


]).replaceIngredient({item:

Item.of('minecraft:potion', {Potion: "minecraft:water"})}, 'minecraft:glass_bottle')})


Events

WorldgenAddEventJS
This event isn't complete yet and can only do basic things. Adding dimension-specific

features also isn't possible yet, but is planned.

Example script: (kubejs/startup_scripts/worldgen.js)

onEvent('worldgen.add', event => {

event.addLake(lake => { // Create new lake feature lake.block =

'minecraft:diamond_block' // Block ID (Use [] syntax for properties) lake.chance = 3 //

Spawns every ~3 chunks

})

event.addOre(ore => { ore.block = 'minecraft:glowstone' // Block ID (Use [] syntax for

properties)

ore.spawnsIn.blacklist = false // Inverts spawn whitelist ore.spawnsIn.values = [ //

List of valid block IDs or tags that the ore can spawn in

'#minecraft:base_stone_overworld' // Default behavior - ores spawn in all stone types

ore.biomes.blacklist = true // Inverts biome whitelist ore.biomes.values = [ // Biomes

this ore can spawn in

'minecraft:plains', // Biome ID '#nether' // OR #category, see list of categories

below

ore.clusterMinSize = 5 // Min blocks per cluster (currently ignored, will be

implemented later, it's always 1)

ore.clusterMaxSize = 9 // Max blocks per cluster ore.clusterCount = 30 // Clusters per

chunk

ore.minHeight = 0 // Min Y ore spawns in

ore.maxHeight = 64 // Max Y ore spawns in ore.squared = true // Adds random value to X

and Z between 0 and 16. Recommended to be true // ore.chance = 4 // Spawns the ore every

~4 chunks. You usually combine this with clusterCount = 1 for rare ores

})
event.addSpawn(spawn => { // Create new entity spawn spawn.category = 'creature' //

Category, can be one of 'creature', 'monster', 'ambient', 'water_creature' or

'water_ambient'

spawn.entity = 'minecraft:pig' // Entity ID

spawn.weight = 10 // Weight

spawn.minCount = 4 // Min entities per group spawn.maxCount = 4 // Max entities per

group

})})

All values are optional. All feature types have biomes field like addOre example

Valid biome categories ('#category'):

taiga

extreme_hills

jungle

mesa

plains

savanna

icy

the_end

beach

forest

ocean

desert

river

swamp

mushroom

nether

You can also use ('$type' (case doesn't matter)) on Forge's BiomeDictionary:

hot

cold
wet

dry

sparse

dense

spooky

dead

lush

etc.... see BiomeDictionary for more

This is the order vanilla worldgen happens:

1. raw_generation

2. lakes

3. local_modifications

4. underground_structures

5. surface_structures

6. strongholds

7. underground_ores

8. underground_decoration

9. vegetal_decoration

10. top_layer_modification

It's possible you may not be able to generate some things in their layer, like ores in dirt,

because dirt hasn't spawned yet. So you may have to change the layer by calling

ore.worldgenLayer = 'top_layer_modification' . But this is not recommended.

If you want to remove things, see this event.


Events

WorldgenRemoveEventJS
For more information on biomes field, see worldgen.add event page.

onEvent('worldgen.remove', event => {

event.removeOres(ores => { ores.blocks = [ 'minecraft:coal_ore', 'minecraft:iron_ore' ]

// Removes coal and iron ore ores.biomes.values = [ 'minecraft:plains' ] // Removes it

only from plains biomes

})

event.removeSpawnsByID(spawns => {

spawns.entities.values = [

'minecraft:cow',

'minecraft:chicken',

'minecraft:pig',

'minecraft:zombie'

})

event.removeSpawnsByCategory(spawns => {

spawns.biomes.values = [

'minecraft:plains'

spawns.categories.values = [

'monster'

})})

If something isn't removing, you may try to remove it "manually" by first printing all features (this

will spam your console a lot, I suggest reading logs/kubejs/startup.txt) and then removing them by

ID where possible.

onEvent('worldgen.remove', event => { // May be one of the decoration types/levels described


in worldgen.add docs

// But ores are *most likely* to be generated in this one

event.printFeatures('underground_ores')})

onEvent('worldgen.remove', event => { event.removeFeatureById('underground_ores',

'mekanism:ore_copper')})
Events

ItemTooltipEventJS
onEvent('item.tooltip', tooltip => {

// Add tooltip to all of these items tooltip.add(['quark:backpack', 'quark:magnet',

'quark:crate'], 'Added by Quark Oddities')

// You can also use any ingredient except #tag tooltip.add(/refinedstorage:red_/, 'Can be

any color') // Multiple lines with an array []. You can also escape ' by using other type of

quotation marks tooltip.add('thermal:latex_bucket', ["Not equivalent to Industrial

Foregoing's Latex", 'Line 2'])

tooltip.addAdvanced('thermal:latex_bucket', (item, advanced, text) => { text.add(0,

Text.of('Hello')) // Adds text in first line, replacing title. If you want 2nd line, the

index must be 1

})})
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
boolean Checks equality with another object.
other)

Hash code of this object. It is used to optimize maps and other


hashCode() int
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 === ''

Returns a copy of this string, but with all characters in


toLowerCase() String
upper case

Returns a copy of this string, but with all characters in


toUpperCase() String
lower case

equalsIgnoseCase( Hash code of this object. It is used to optimize maps and


boolean
String other) 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.

32 bit decimal number, most common decimal


int Integer
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 '-' .

Only true and false values. Can be checked


in if function without comparing to true, as
boolean Boolean
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

KubeJS UI
You can also always look at existing modpack using KubeJS UI to see how they do it

onEvent('ui.main_menu', event => {

event.replace(ui => {

//ui.background('kubejsui:textures/example_background.png')

ui.tilingBackground('kubejsui:textures/example_background.png', 256)

ui.minecraftLogo(30)

ui.button(b => {

b.name = 'Test'

b.x = 10

b.y = 10

b.action = 'minecraft:singleplayer'

})

ui.button(b => {

b.name = 'Test but in bottom right corner'

b.x = ui.width - b.width - 10

b.y = ui.height - b.height - 10

b.action = 'https://feed-the-beast.com/'

})

ui.label(l => {

l.name = text.yellow('FTB Stranded')

l.x = 2

l.y = ui.height - 12

l.action = 'https://feed-the-beast.com/'

})

ui.image(i => {

i.x = (ui.width - 40) / 2

i.y = (ui.height - 30) / 2

i.width = 40

i.height = 30
i.action = 'https://feed-the-beast.com/'

})

ui.label(l => {

l.name = text.aqua('Large label')

l.x = 100

l.y = ui.height - 20

l.height = 15

l.shadow = true

})

})})
Examples

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()]

maxStackSize(size)
unstackable()

maxDamage(damage)

burnTime(ticks)

containerItem(item_id)

rarity('rarity')

tool(type, level)

glow(true/false)

tooltip(text...)

group('group_id')

color(index, colorHex)

texture(customTexturePath)

parentModel(customParentModel)

food(foodBuilder => ...)

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

tier('toolTier')

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)

Valid tool tiers:

wood

stone

iron

gold

diamond

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

tier('armorTier')

modifyTier(tier => ...) // Same syntax as custom armor tier, see below

Valid armor tiers:

leather

chainmail

iron

gold

diamond

turtle

netherite

Valid group/creative tab IDs:

search

buildingBlocks

decorations

redstone

transportation

misc

food

tools

combat

brewing

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 Blocks
This is a startup script.

onEvent('block.registry', event => {

event.create('test_block')

.material('glass')

.hardness(0.5)

.displayName('Test Block') // No longer required in 1.18.2+

// Block with custom type (see below for list of types) event.create('test_block_slab',

'slab').material('glass').hardness(0.5)})

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
Material

earth

water

lava

leaves

plants

sponge

wool

sand

glass

tnt

coral

ice

snow

clay

groud

dragon_egg

portal

cake

web

slime

honey

berry_bush
Material

lantern

Other methods block builder supports: [you can chain these methods]

displayName('name') // Not required for 1.18.2+

material('material')

type('basic') // See available types below

hardness(float) // >= 0.0

resistance(float) // >= 0.0

unbreakable()

lightLevel(int) // 0.0 - 1.0

harvestTool('tool', level) // Available tools: pickaxe, axe, hoe, shovel, level >= 0

opaque(boolean)

fullBlock(boolean)

requiresTool(boolean)

renderType('type') // solid, cutout, translucent, cutout required for blocks with texture like

glass, translucent required for blocks like stained glass

color(tintindex, color)

texture('texturepath')

texture('side', 'texturepath')

model('modelpath')

noItem()

box(x0, y0, z0, x1, y1, z1, true) // 0.0 - 16.0, default is (0,0,0,16,16,16, true)

box(x0, y0, z0, x1, y1, z1, false) // Same as above, but in 0.0 - 1.0 scale, default is

(0,0,0,1,1,1, false)

noCollision()

notSolid()

waterlogged()

noDrops()

slipperiness(float) // 
speedFactor(float)

jumpFactor(float)

randomTick(randomTickEvent => {}) // see below

item(itemBuilder => {})

setLootTableJson(json)

setBlockstateJson(json)

setModelJson(json)

noValidSpawns(boolean)

suffocating(boolean)

viewBlocking(boolean)

redstoneConductor(boolean)

transparent(boolean)

defaultCutout() // batches a bunch of methods to make blocks such as glass

defaultTranslucent() // similar to defaultCutout() but using translucent layer instead

tag('forge:something') // adds a block tag

tagBlockAndItem('forge:something') // adds both block and item tag

Event callbacks:

RandomTickEvent:

BlockContainerJS block

Random random

Types

basic

slab

stairs

fence

fence_gate

wall

wooden_pressure_plate

stone_pressure_plate

wooden_button
stone_button
Examples

Loot Table Modification


onEvent('block.loot_tables', event => { event.addSimpleBlock('minecraft:dirt',

'minecraft:red_sand')})

onEvent('block.loot_tables', event => { event.addSimpleBlock('minecraft:dirt') // To drop

itself (fix broken blocks) event.addSimpleBlock(/minecraft:.*_ore/, 'minecraft:red_sand') //

To drop a different item})

onEvent('block.loot_tables', event => { event.addBlock('minecraft:dirt', table => { // Build

loot table manually

table.addPool(pool => {

pool.rolls = 1 // fixed // pool.rolls = [4, 6] // or {min: 4, max: 6} //

uniform

// pool.rolls = {n: 4, p: 0.3} // binominal

pool.survivesExplosion()

pool.addItem('minecraft:dirt') pool.addItem('minecraft:dirt', 40) // 40 =

weight pool.addItem('minecraft:dirt', 40, [4, 8]) // [4-8] = count modifier, uses same

syntax as rolls

// pool.addCondition({json condition, see vanilla wiki}) // pool.addEntry({json

entry, see vanilla wiki for non-items})

})

})})

Example from Factorial: (adds 1-3 leaves dropped from all Leaves blocks, 4-8 logs from all log and

wood blocks and 4-8 stone from Stone, Cobblestone, Andesite, Diorite and Granite)

onEvent('block.loot_tables', event => {

event.addBlock(/minecraft:.*_leaves/, table => {

table.addPool(pool => {

pool.survivesExplosion()

pool.addItem('factorial:leaf', 1, [1, 3])

})

})
event.addBlock(/minecraft:.*_(log|wood)/, table => {

table.addPool(pool => {

pool.survivesExplosion()

pool.addItem('factorial:wood', 1, [4, 8])

})

})

event.addBlock([

'minecraft:stone',

'minecraft:cobblestone',

'minecraft:andesite',

'minecraft:diorite',

'minecraft:granite'

], table => {

table.addPool(pool => {

pool.rolls = [4, 8] // Roll the pool instead of individual items

pool.survivesExplosion()

pool.addItem('factorial:stone', 1)

})

})})

You can also modify existing loot tables to add items to them:

onEvent('block.loot_tables', event => { // all dirt blocks have a 50% chance to drop an

enchanted diamond sword named "test"

event.modifyBlock(/^minecraft:.*dirt/, table => {

table.addPool(pool => {

pool.addItem('minecraft:diamond_sword').randomChance(0.5).enchantWithLevels(1,

true).name(Text.of('Test').blue())

})

})})

Other loot table types work too:

onEvent('entity.loot_tables', event => { // Override zombie loot table that will drop 5 of

either carrot (25% chance) or apple (75% chance) event.addEntity('minecraft:zombie', table

=> {

table.addPool(pool => {

pool.rolls = 5

pool.addItem('minecraft:carrot', 1)
pool.addItem('minecraft:apple', 3)

})

})

event.modifyEntity('minecraft:pig', table => {

table.addPool(pool => { // Modify pig loot table to *also* drop dirt on top of its

regular drops

pool.addItem('minecraft:dirt')

})

})})

Supported table types:

Override method
Event ID Modify method name
name

generic.loot_tables addGeneric modify

block.loot_tables addBlock modifyBlock

entity.loot_tables addEntity modifyEntity

gift.loot_tables addGift modify

fishing.loot_tables addFishing modify

chest.loot_tables addChest modify

 
Examples

Item Modification
item.modification event is a startup script event that allows you to change properties of existing

items

onEvent('item.modification', event => {

event.modify('minecraft:ender_pearl', item => {

item.maxStackSize = 64

item.fireResistant = true

})})

All available properties:

int maxStackSize

int maxDamage

int burnTime

String craftingReminder

boolean fireResistant

Rarity rarity

tier = tierOptions => {

int uses

float speed

float attackDamageBonus

int level

int enchantmentValue

Ingredient repairIngredient

foodProperties = food => { // note: uses functions instead of a = b

hunger(int)

saturation(float)

meat(boolean)
alwaysEdible(boolean)

fastToEat(boolean)

effect(String effectId, int duration, int amplifier, float probability)

removeEffect(String effectId)

}
Examples

Block Modification
block.modification event is a startup script event that allows you to change properties of existing

blocks

onEvent('block.modification', event => {

event.modify('minecraft:stone', block => {

block.destroySpeed = 0.1

block.hasCollision = false

})})

All available properties:

String material

boolean hasCollision

float destroySpeed

float explosionResistance

boolean randomlyTicking

String soundType

float friction

float speedFactor

float jumpFactor

int lightEmission

boolean requiredTool
Examples

JEI Integration
Sub-types

onEvent('jei.subtypes', event => {

event.useNBT('example:item')

event.userNBTKey('example:item', 'type')})

Hide Items & Fluids

onEvent('jei.hide.items', event => {

event.hide('example:ingredient')

})

onEvent('jei.hide.fluids', event => {

event.hide('example:fluid')})

Add Items & Fluids

onEvent('jei.add.items', event => {

event.add(Item.of('example:item', {test: 123}))

})

onEvent('jei.add.fluids', event => {

event.add('example:fluid')})

Add Information

onEvent('jei.information', event => {

event.add('example:ingredient', ['Line 1', 'Line 2'])})


Examples

REI Integration
Note: REI integration only works on Fabric in 1.16. In 1.18+, it works on both Forge and

Fabric!

Hide Items

onEvent('rei.hide.items', event => {

event.hide('example:ingredient')})

Add Items

onEvent('rei.add.items', event => {

event.add(item.of('example:item').nbt({test: 123}))})

Add Information

onEvent('rei.information', event => { event.add('example:ingredient', 'Title', ['Line 1',

'Line 2'])})
Examples

FTB Quests Integration


onEvent('ftbquests.custom_task.75381f79', event => {

log.info('Custom task!')

event.checkTimer = 20

event.check = (task, player) => { if (player.world.daytime && player.world.raining)

task.progress++

})

onEvent('ftbquests.custom_reward.e4f76908', event => {

log.info('Custom reward!')

event.player.tell('Hello!')

})

// specific object completion

onEvent('ftbquests.completed.d4f36905', event => {

if (event.player) { event.notifiedPlayers.tell(Text.of(`${event.player.name}

completed... something!`).green())

})

// generic 'quest' object completion. Note: There isnt actually a way to get reliable title

on server side, so dont use event.object.title

onEvent('ftbquests.completed', event => { if (event.player && event.object.objectType.id ===

'quest') { event.notifiedPlayers.tell(Text.of(`${event.player.name} completed a

quest!`).blue())

})

// object with tag 'ding' completion

onEvent('ftbquests.completed.ding', event => {

event.onlineMembers.playSound('entity.experience_orb.pickup')

})

onEvent('entity.death', event => {

if(event.server

&& event.source.actual
&& event.source.actual.player && event.source.actual.mainHandItem.id ===

'minecraft:wooden_sword'

&& event.entity.type === 'minecraft:zombie') {

event.source.actual.data.ftbquests.addProgress('12345678', 1)

}})
Examples

Reflection / Java access


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

onEvent('postinit', event => {

// Loads Java class field

var PECore = java('moze_intel.projecte.PECore') // Changes public static boolean

DEV_ENVIRONMENT of PECore class to false

PECore.DEV_ENVIRONMENT = false})
Examples

Painter API
About

Painter API allows you to draw things on the screen, both from server and directly from client. This

can allow you to create widgets from server side or effects on screen or in world from client side.

Currently it doesn't support any input, but in future, in-game menus or even GUIs similar to Source

engine ones will be supported.

Paintable objects are created from NBT/Json objects and all have an id. If id isn't provided, a

random one will be generated. Objects x and z are absolute positions based on screen, but you

can align elements in one of the corners of screen. You can bulk add multiple objects in one json

object. All properties are optional, but obviously some you should almost always override like size

and position for rectangles.

paint({...}) is based on upsert principle - if object doesn't exist it will create it (if the object also

contains valid type ), otherwise, update existing:

event.player.paint({example: {type: 'rectangle', x: 10, y: 10, w: 20, h: 20}}) - New

rectangle is created

event.player.paint({example: {x: 50}}) - Updates previous rectangle with partial data

You can bulk update/create multiple things in same object:

event.player.paint({a: {x: 10}, b: {x: 30}, c: {type: 'rectangle', x: 10}})

You can remove object with remove: true, bulk remove multiple objects or remove all objects:

event.player.paint({a: {remove: true}})


event.player.paint({a: {remove: true}, b: {remove: true}})
event.player.paint({'*': {remove: true}})
These methods have command alternatives:

/kubejs painter @p {example: {type: 'rectangle', x: 10, y: 10, w: 20, h: 20}}

If the object is re-occuring, it's recommended to create objects at login with all of its static

properties and visible: false , then update it later to unhide it. Painter objects will be cleared

when players leave world/server, if its persistent, then it must be re-added at login every time.

Currently available objects

Underlined objects are not something you can create

Root

(available for all objects)

Boolean visible

Screen Object

(available for all screen / 2D objects)

Unit x

Unit y

Unit z

Unit w

Unit h

Enum alignX (one of 'left', 'center', 'right')

Enum alignY (one of 'top', 'center', 'bottom')

Enum draw (one of 'ingame', 'gui', 'always')

Unit moveX

Unit moveY

Unit expandW

Unit expandH
rectangle

Color color

String texture

Float u0

Float v0

Float u1

Float v1

gradient

Color color

Color colorT

Color colorB

Color colorL

Color colorR

Color colorTL

Color colorTR

Color colorBL

Color colorBR

String texture

Float u0

Float v0

Float u1

Float v1

text

Text text

Boolean shadow

Float scale

Color color

Boolean centered
World Object (not implemented!)

Unit x

Unit y

Unit z

Unit w

Unit h

Unit d

Properties

Unit is a Rhino Unit

Int is a int32 number, any whole value, e.g. 40

Float is floating point number, e.g 2.35

String is a string, e.g. 'example' . Textures usually need resource location


'namespace:path/to/texture.png'

Color can be either 0xRRGGBB , '#RRGGBB' , '#AARRGGBB', e.g. '#58AD5B' or chat colors 'red' ,

'dark_aqua' , etc.

Text can be a string 'Example' or Text.of('Red and italic string example').red().italic()

etc formatted string.

Available Unit variables

$screenW - Screen width

$screenH - Screen height

$delta - Render delta

$mouseX - Mouse X position

$mouseY - Mouse Y position

Examples

onEvent('player.logged_in', event => {

event.player.paint({

example_rectangle: {
type: 'rectangle',

x: 10,

y: 10,

w: 50,

h: 20,

color: '#00FF00',

draw: 'always'

},

last_message: {

type: 'text',

text: 'No last message',

scale: 1.5,

x: -4,

y: -4,

alignX: 'right',

alignY: 'bottom',

draw: 'always'

})

})

onEvent('player.chat', event => { // Updates example_rectangle x value and last_message text

value to last message + contents from event event.player.paint({example_rectangle: {x:

'(sin((time() * 1.1)) * (($screenW - 32) / 2))', w: 32, h: 32, alignX: 'center', texture:

'kubejs:textures/item/diamond_ore.png'}}) event.player.paint({last_message: {text: `Last

message: ${event.message}`}}) // Bulk update, this is the same code as 2 lines above, you can

use whichever you like better // event.player.paint({example_rectangle: {x: 120},

last_message: {text: `Last message: ${event.message}`}}) event.player.paint({lava: {type:

'atlas_texture', texture: 'minecraft:block/lava_flow'}})})


Examples

Units
This page describes all functions and operations available for units

Usage

Most basic unit is plain number, such as '1' or '4.5' . You can use variables with $ like

'$example' . Each operation requires parenthesis around it, e.g '(10 + $example)' . each function

requires name parenthesis and comma separated arguments e.g. 'min(PI, $example)' . You can

combine as many as you want, e.g. 'min(PI, (10 + $example))' .

Constants

PI == 3.141592653589793

E == 2.718281828459045

true == 1.0

false == 0.0

Operations

-a

(a + b)

(a - b)

(a * b)

(a / b)

(a % b)

(a & b)

(a | b)

(a ^ b)

!a

(a << b)

(a >> b)
(a == b)

(a != b)

(a > b)

(a < b)

(a >= b)

(a <= b)

Functions

random()

time()

min(a, b)

max(a, b)

pow(a, b)

abs(a)

sin(a)

cos(a)

tan(a)

atan(a)

atan2(y, x)

deg(a)

rad(a)

log(a)

log10(a)

log1p(a)

sqrt(a)

sq(a)

floor(a)

ceil(a)

if(statement, trueUnit, falseUnit)


Examples

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

"Aw man".

onEvent('player.chat', (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, (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,

onEvent('player.chat', (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// This goes in either server or

client script, depending on which side you want to send the data packet to

onEvent('item.right_click', event => { // Check if item was right-clicked on client or

server side

if (event.server) { // 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 be client (because its sent 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 be server (because its sent from client).

event.player.sendData('test_channel_2', { test: 456 })

})

// Listen to event that gets fired when network packet is received from server.// This goes

in a client script

onEvent('player.data_from_server.test_channel_1', event => { log.info(event.data.test) //

Prints 123

})

// Listen to event that gets fired when network packet is received from client.// This goes

in a server script

onEvent('player.data_from_client.test_channel_2', event => { log.info(event.data.test) //

Prints 456})
Examples

Starting Items
This server script adds items on first time player joins, checking stages. GameStages mod is not

required

// Listen to player login event

onEvent('player.logged_in', event => { // Check if player doesn't have "starting_items"

stage yet

if (!event.player.stages.has('starting_items')) {

// Add the stage

event.player.stages.add('starting_items')

// Give some items to player

event.player.give('minecraft:stone_sword')

event.player.give(Item.of('minecraft:stone_pickaxe', "{Damage: 10}"))

event.player.give('30x minecraft:apple')

}})
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: 15ftbutilities.chat.name_format: <&aNewcomer &r{name}>

command.ftbutilities.rtp: true

[regular]

power: 10

promotion.name: Regular

promotion.next: trusted

promotion.timer: 30ftbutilities.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 1.12
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 clearlagvar whitelist =

Ingredient.matchAny([

'minecraft:diamond', // Adds diamond to whitelist

'minecraft:gold_ingot', '@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 itemsvar lastTotalClearLagResult =

Utils.newCountingMap()

// Create new function that clears lag

var 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(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', 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,

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, callback2 => {

clearLag(callback2.data)

})

// Re-schedule this task for another 30 minutes (endless loop)

callback.reschedule()

})

})

// Doesnt work in 1.16+!

// Register commands

events.listen('command.registry', 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((sender, args) => { sender.tell([ Text.lightPurple('[ClearLag]'), ' Last

clearlag results:' ])

lastClearLagResult.forEach(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.

onEvent('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

Changing Window Title and


Icon
Yes, you can do that with KubeJS too.

To change title, all you have to do is change title in kubejs/config/client.properties .

To change icon, you create a kubejs/config/packicon.png image in standard Minecraft

texture size preferably (64x64, 128x128, 256x256, that kind of size).

The image has to be saved as 32-bit PNG, not Auto-detect/24-bit, otherwise you will get a

JVM crash!

Here's how to do that in PaintNET:

Example result:
Currently incompatible with Fancy Menu!
Examples

Custom Fluids
Fabric not supported yet!

onEvent('fluid.registry', event => {

// Basic "thick" (looks like lava) fluid with red tint event.create('thick_fluid', fluid

=> {

fluid.textureThick(0xFF0000)

fluid.bucketColor(0xFF0000)

fluid.displayName('Thick Fluid')

})

// Basic "thin" (looks like water) fluid with cyan tint event.create('thick_fluid', fluid

=> {

fluid.textureThin(0xFF0000)

fluid.bucketColor(0x00FFFF)

fluid.displayName('Thin Fluid')

})

// Fluid with custom textures

event.create('strawberry_cream', fluid => {

fluid.displayName('Strawberry Cream')

fluid.textureStill('kubejs:block/strawberry_still')

fluid.textureFlowing('kubejs:block/strawberry_flow')

fluid.bucketColor(0xFF33FF)

})

// as always, for KubeJS 3 / Minecraft 1.16, these calls need to be chained instead, so

for example

event.create('thick_fluid')

.textureThick(0xFF0000)

.bucketColor(0xFF0000)

.displayName('Thick Fluid')})

You might also like