# Addons



# KubeJS UI

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/kubejs-ui)

No info yet!

# KubeJS Create

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/kubejs-create), [Modrinth](https://modrinth.com/mod/kubejs-create)

<p class="callout info">The example scripts are only here to demonstrate the recipes. They are not meant to be used with the items shown.</p>

##### Compacting

Syntax: `compacting(output[], input[])`

Features:

- supports multiple inputs and outputs
- supports `.heated()` and `.superheated()`
- can have a fluid output as long as it has another item output
- supports chance-based output
- uses the **Mechanical Press**, **Basin**, and optionally a **Blaze Burner**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.compacting('diamond', 'coal_block')
  e.recipes.create.compacting('diamond', 'coal_block').heated()
  e.recipes.create.compacting('diamond', 'coal_block').superheated()
  e.recipes.create.compacting([Fluid.water(10), 'dead_bush'], ['#minecraft:saplings', '#minecraft:saplings'])
  e.recipes.create.compacting(['diamond', Item.of('diamond').withChance(0.3)], 'coal_block')
})
```

---

##### Crushing

Syntax: `crushing(output[], input)`

Features:

- supports multiple chance-based outputs
- supports `.processingTime()`
- uses the **Crushing Wheels**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.crushing('diamond', 'coal_block')
  e.recipes.create.crushing('diamond', 'coal_block').processingTime(500)
  e.recipes.create.crushing(['diamond', Item.of('diamond').withChance(0.5)], 'coal_block')
})
```

---

##### Cutting

Syntax: `cutting(output[], input)`

Features:

- supports multiple chance-based outputs
- supports `.processingTime()`
- uses the **Mechanical Saw**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.cutting('diamond', 'coal_block')
  e.recipes.create.cutting('diamond', 'coal_block').processingTime(500)
  e.recipes.create.cutting(['diamond', Item.of('diamond').withChance(0.5)], 'coal_block')
})
```

---

##### Deploying

Syntax: `deploying(output[], input[])`

Features:

- supports multiple chance-based outputs
- requires exactly two inputs, the second input is what the Deployer is holding
- supports `.keepHeldItem()`
- uses the **Deployer**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.deploying('diamond', ['coal_block', 'sand'])
  e.recipes.create.deploying(['diamond', 'emerald'], ['coal_block', 'sand']).keepHeldItem()
  e.recipes.create.deploying(['diamond', Item.of('diamond').withChance(0.5)], ['coal_block', 'sand'])
})
```

---

##### Emptying

Syntax: `emptying(output[], input)`

Features:

- requires one input and two outputs, the outputs must be an item and a fluid
- uses the **Item Drain**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.emptying([Fluid.water(), 'bucket'], 'water_bucket')
})
```

---

##### Filling

Syntax: `filling(output, input[])`

Features:

- requires two inputs and one output, the inputs must be an item and a fluid
- uses the **Spout**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.filling('water_bucket', [Fluid.water(), 'bucket'])
})
```

---

##### Haunting

Syntax: `haunting(output[], input)`

Features:

- supports multiple chance-based outputs
- uses the **Encased Fan** and **Soul Fire**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.haunting('soul_campfire', 'campfire')
  e.recipes.create.haunting(['wheat', 'oak_sapling'], 'potato')
  e.recipes.create.haunting(['wheat', Item.of('oak_sapling').withChance(0.2)], 'potato')
})
```

---

##### Mechanical Crafting

Syntax: `mechanical_crafting(output, pattern[], keys{})`

Features:

- mostly identical to the default Shaped Crafting
- supports up to 9x9 grid size
- uses the **Mechanical Crafter**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.mechanical_crafting('emerald', [
    ' DDD ',
    'D   D',
    'D   D',
    'D   D',
    ' DDD '
  ], {
    D: 'dirt'
  })
})
```

---

##### Milling

Syntax: `milling(output[], input)`

Features:

- supports multiple chance-based outputs
- uses the **Millstone**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.milling('diamond', 'coal_block')
  e.recipes.create.milling(['diamond', 'emerald'], 'coal_block')
  e.recipes.create.milling(['diamond', Item.of('diamond').withChance(0.5)], 'coal_block')
})
```

---

##### Mixing

Syntax: `mixing(output[], input)`

Features:

- supports multiple chance-based outputs
- supports fluid inputs and outputs
- supports `.heated()` and `.superheated()`
- uses the **Mechanical Mixer,** **Basin**, and optionally a **Blaze Burner**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.mixing('diamond', 'coal_block')
  e.recipes.create.mixing('diamond', 'coal_block').heated()
  e.recipes.create.mixing('diamond', 'coal_block').superheated()
  e.recipes.create.mixing([Fluid.water(10), 'dead_bush'], ['#minecraft:saplings', '#minecraft:saplings'])
  e.recipes.create.mixing(['diamond', Item.of('diamond').withChance(0.3)], 'coal_block')
})
```

---

##### Pressing

Syntax: `pressing(output[], input)`

Features:

- supports multiple chance-based outputs
- uses the **Mechanical Press**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.pressing('diamond', 'coal_block')
  e.recipes.create.pressing(['diamond', 'emerald'], 'coal_block')
  e.recipes.create.pressing(['diamond', Item.of('diamond').withChance(0.5)], 'coal_block')
})
```

---

##### Sandpaper Polishing

Syntax: `sandpaper_polishing(output, input)`

Features:

- supports chance-based output
- uses any item tagged with `create:sandpaper`

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.sandpaper_polishing('diamond', 'coal_block')
  e.recipes.create.sandpaper_polishing(Item.of('diamond').withChance(0.5), 'coal_block')
})
```

---

##### Sequenced Assembly

Syntax: `sequenced_assembly(output[], input, sequence[]).transitionalItem(item).loops(int)`

`Output` is an item or an array of items. If it is an array:

- The first item is the real output, the remainder is scrap.
- Only one item is chosen, with an equal chance of each.
- You can use `Item.of('create:shaft').withChance(2)` to double the chance of that item being chosen.

`Transitional Item` is any item used during the intermediate stages of the assembly.

`Sequence` is an array of recipes of the following types:

- `create:cutting`
- `create:pressing`
- `create:deploying`
- `create:filling`

The transitional item needs to be the input ***and*** output of each of these recipes.

`Loops` is the number of times that the recipe repeats. Calling `.loops()` is optional and defaults to **4**.

```javascript
ServerEvents.recipes(e => {
	e.recipes.create.sequenced_assembly([
		Item.of('create:precision_mechanism').withChance(130.0), // this is the item that will appear in JEI as the result
		Item.of('create:golden_sheet').withChance(8.0), // the rest of these items will be part of the scrap
		Item.of('create:andesite_alloy').withChance(8.0),
		Item.of('create:cogwheel').withChance(5.0),
		Item.of('create:shaft').withChance(2.0),
		Item.of('create:crushed_gold_ore').withChance(2.0),
		Item.of('2x gold_nugget').withChance(2.0),
		'iron_ingot',
		'clock'
	], 'create:golden_sheet', [ // 'create:golden_sheet' is the input
		// the transitional item set by `transitionalItem('create:incomplete_large_cogwheel')` is the item used during the intermediate stages of the assembly
		e.recipes.createDeploying('create:incomplete_precision_mechanism', ['create:incomplete_precision_mechanism', 'create:cogwheel']),
		// like a normal recipe function, is used as a sequence step in this array. Input and output have the transitional item
		e.recipes.createDeploying('create:incomplete_precision_mechanism', ['create:incomplete_precision_mechanism', 'create:large_cogwheel']),
		e.recipes.createDeploying('create:incomplete_precision_mechanism', ['create:incomplete_precision_mechanism', 'create:iron_nugget'])
	]).transitionalItem('create:incomplete_precision_mechanism').loops(5) // set the transitional item and the number of loops

	// for this code to work, kubejs:incomplete_spore_blossom needs to be added to the game
	let inter = 'kubejs:incomplete_spore_blossom' // making a variable to store the transitional item makes the code more readable
	e.recipes.create.sequenced_assembly([
		Item.of('spore_blossom').withChance(16.0), // this is the item that will appear in JEI as the result
		Item.of('flowering_azalea_leaves').withChance(16.0), // the rest of these items will be part of the scrap
		Item.of('azalea_leaves').withChance(2.0),
		'oak_leaves',
		'spruce_leaves',
		'birch_leaves',
		'jungle_leaves',
		'acacia_leaves',
		'dark_oak_leaves'
	], 'flowering_azalea_leaves', [ // 'flowering_azalea_leaves' is the input
		// the transitional item is a variable, that is 'kubejs:incomplete_spore_blossom' and is used during the intermediate stages of the assembly
		e.recipes.createPressing(inter, inter),
		// like a normal recipe function, is used as a sequence step in this array. Input and output have the transitional item
		e.recipes.createDeploying(inter, [inter, 'minecraft:hanging_roots']),
		e.recipes.createFilling(inter, [inter, Fluid.water(420)]),
		e.recipes.createDeploying(inter, [inter, 'minecraft:moss_carpet']),
		e.recipes.createCutting(inter, inter)
	]).transitionalItem(inter).loops(2) // set the transitional item and the number of loops
})
```

##### Transitional Items

As mentioned earlier, any item can be a transition item. However, this is not completely recommended.

If you wish to make your own transitional item, it's best if you make the type `create:sequenced_assembly`.

```javascript
StartupEvents.registry('item', e => {
	e.create('incomplete_spore_blossom', 'create:sequenced_assembly')
})
```

---

##### Splashing/Washing

Syntax: `splashing(output[], input)`

Features:

- supports multiple chance-based outputs
- uses the **Encased Fan** and **Water**

```javascript
ServerEvents.recipes(e => {
  e.recipes.create.splashing('soul_campfire', 'campfire')
  e.recipes.create.splashing(['wheat', 'oak_sapling'], 'potato')
  e.recipes.create.splashing(['wheat', Item.of('oak_sapling').withChance(0.2)], 'potato')
})
```










---

##### Mysterious Conversion

<p class="callout warning">Mysterious Conversion recipes are client-side only, so the only way to add them currently is using reflection.</p>

<p class="callout warning">Goes inside `<strong>client_scripts</strong>` and ***not*** in an event.</p>

```JavaScript
//reference the classes used for the recipe
let MysteriousItemConversionCategory = Java.loadClass('com.simibubi.create.compat.jei.category.MysteriousItemConversionCategory')
let ConversionRecipe = Java.loadClass('com.simibubi.create.compat.jei.ConversionRecipe')

//add the recipes manually
MysteriousItemConversionCategory.RECIPES.add(ConversionRecipe.create('apple', 'carrot'))
MysteriousItemConversionCategory.RECIPES.add(ConversionRecipe.create('golden_apple', 'golden_carrot'))
```

---

##### Preventing Recipe Auto-Generation

If you don't want smelting, blasting, smoking, crafting, or stonecutting to get an auto-generated counterpart, then include `manual_only` at the end of the recipe id:

```JavaScript
ServerEvents.recipes(e => {
	e.shapeless('wet_sponge', ['water_bucket', 'sponge']).id('kubejs:moisting_the_sponge_manual_only')
})
```

Other types of prevention, can be done in the create config (the goggles button leads you there).

If it is not in the config, then you can not change it.

# KubeJS Thermal

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/kubejs-thermal), [Modrinth](https://modrinth.com/mod/kubejs-thermal)

<p class="callout warning">This info is currently incomplete!</p>

Supported recipe types:

\- furnace  
\- sawmill  
\- pulverizer  
\- smelter  
\- centrifuge  
\- press  
\- crucible  
\- chiller  
\- refinery  
\- brewer  
\- bottler

event.recipes.thermal.press('minecraft:bone', '#forge:dyes/black')  
event.recipes.thermal.crucible(Fluid.of('minecraft:water', 300), '#minecraft:saplings')

\- insolator

event.recipes.thermal.insolator('minecraft:bone', '#forge:dyes/black').water(400)

\- pulverizer\_catalyst  
\- smelter\_catalyst  
\- insolator\_catalyst

event.recipes.thermal.pulverizer\_catalyst('minecraft:coal').primaryMod(1.0).secondaryMod(1.0).energyMod(1.0).minChance(0.0).useChance(1.0)

\- stirling\_fuel  
\- compression\_fuel  
\- magmatic\_fuel  
\- numismatic\_fuel  
\- lapidary\_fuel

event.recipes.thermal.lapidary\_fuel('minecraft:coal').energy(100000)

# KubeJS Mekanism

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/kubejs-mekanism), [Modrinth](https://modrinth.com/mod/kubejs-mekanism)

No info yet!

# KubeJS Immersive Engineering

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/kubejs-immersive-engineering), [Modrinth](https://modrinth.com/mod/kubejs-immersive-engineering)

No info yet!

# KubeJS Blood Magic

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/kubejs-blood-magic)

No info yet!

# KubeJS Tinkers Construct

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/kubejs-tinkers-construct)

No info yet!

# PonderJS

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/ponderjs)

No info yet!

# LootJS

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/lootjs), [Modrinth](https://modrinth.com/mod/lootjs)

No info yet!

# ProbeJS

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/probejs)

No info yet!

# KubeJS Additions

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/kubejs-additions), [Modrinth](https://modrinth.com/mod/kubejs-additions)

No info yet!

For more information please see the project's [Github Page](https://github.com/Hunter19823/kubejsadditions#kubejs-additions), which has usage examples and documentation.

# MoreJS

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/morejs)

No info yet!

# PowerfulJS

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/powerfuljs)

No info yet!

# beJS

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/bejs)

<p class="callout info">The custom BlockEntity event is a startup event.</p>

#### Block Entities

Custom BlockEntities are created in a startup script. They cannot be reloaded without restarting the game. The event is not cancellable.

```javascript
StartupEvents.registry('block', event => {
	event.create('example_block', 'entity' /*has to be here for the BE builder to work*/).displayName('Example Block')
	.entity(builder => { // adds a BlockEntity onto this block
	    builder.ticker((level, pos, state, be) => { // a tick method, called on block entity tick
            if(!level.clientSide) { // ALWAYS check side, the tick method is called on both CLIENT and SERVER
                if(level.levelData.gameTime % 20 == 0) { // only .levelData.gameTime works for some reason??
                    if(level.getBlockState(pos.above()) === Blocks.AIR.defaultBlockState()) {
                        level.setBlock(pos.above(), Blocks.GLASS.defaultBlockState(), 3)
                      	be.persistentData.putBoolean("placed", true)
                    } else {
                        level.setBlock(pos.above(), Blocks.AIR.defaultBlockState(), 3)
                        be.persistentData.putBoolean("placed", false)
                    }
                  	console.info("placed: " + be.persistentData.getBoolean("placed"))
                }
            }
    	}).defaultValues(tag => tag = { progress: 0, example_value_for_extra_saved_data: '0mG this iz Crazyyy'}) // adds a 'default' saved value, added on block entity creation (place etc)
                                                                                                                  // [1st param: CompoundTag consumer]
        .addValidBlock('example_block') // adds a valid block this can attach to, useless in normal circumstances (except if you want to attach to multiple blocks or are building the BE separately)
        .itemHandler(27) // adds a basic item handler to this block entity, use something like PowerfulJS for more advanced functionality
                         // [1st param: slot count]
        .energyHandler(10000, 1000, 1000) // adds a basic FE handler, same as above
                                          // [1st param: max energy, 2nd param: max input, 3rd param: max output]
        .fluidHandler(1000, stack => true) // adds a basic fluid handler
              	                           // [1st param: max amount, 2nd param: fluid filter]
    })
})
```

alternatively, you can create the BlockEntity separately and attach it with `EntityBlockJS.Builder#entity('kubejs:be_id')`

```javascript
StartupEvents.registry('block_entity_type', event => {
	event.create('example_block')
	.ticker((level, pos, state, be) => { // a tick method, called on block entity tick
        if(!level.clientSide) { // ALWAYS check side, the tick method is called on both CLIENT and SERVER
            if(level.levelData.gameTime % 20 == 0) { // only .levelData.gameTime works for some reason??
                if(level.getBlockState(pos.above()) === Blocks.AIR.defaultBlockState()) {
                    level.setBlock(pos.above(), Blocks.GLASS.defaultBlockState(), 3)
                } else {
                    level.setBlock(pos.above(), Blocks.AIR.defaultBlockState(), 3)
                }
            }
        }
    }).saveCallback((level, pos, be, tag) => { // called on BlockEntity save, don't see why you would ever need these tbf, but they're here
        tag.putInt("tagValueAa", be.getPersistentData().getInt('progress'))
    }).loadCallback((level, pos, be, tag) => { // called on BlockEntity load, same as above
          be.getPersistentData().putInt("progress", tag.getInt("tagValueAa"))
    }).defaultValues(tag => tag = { progress: 0, example_value_for_extra_saved_data: '0mG this iz Crazyyy'}) // adds a 'default' saved value, added on block entity creation (place etc)
                                                                                                              // [1st param: CompoundTag consumer]
    .addValidBlock('example_block') // adds a valid block this can attach to, useless in normal circumstances (except if you want to attach to multible blocks)
    .hasGui() // if ScreenJS is installed, marks this blockentity as having a GUI, doesn't do anything otherwise
    .itemHandler(27) // adds a basic item handler to this block entity, use something like PowerfulJS for more advanced functionality
                     // [1st param: slot count]
    .energyHandler(10000, 1000, 1000) // adds a basic FE handler, same as above
                                      // [1st param: max energy, 2nd param: max input, 3rd param: max output]
    .fluidHandler(1000, stack => true) // adds a basic fluid handler
                          	            // [1st param: max amount, 2nd param: fluid filter]
})
```

all valid methods available on all builders:

- `addValidBlock('block_id')`
- `ticker((level, pos, state, blockEntity) => ...)`
- `defaultValues(tag => ...)`
- `itemHandler(capacity)`
- `energyHandler(capacity, maxReceive, maxExtract)`
- `fluidHandler(capacity, fluidStack => isValid)`

#### Multiblocks

multiblock builder example:

```javascript
StartupEvents.registry('block', event => {
    let CAP_PREDICATE = be => { // has *any* forge capability (item, energy, fluid)
        return be != null && (be.getCapability(ForgeCapabilities.ITEM_HANDLER).present || be.getCapability(ForgeCapabilities.FLUID_HANDLER).present || be.getCapability(ForgeCapabilities.ENERGY).present)
    }

	event.create('multi_block', 'multiblock').material('metal').hardness(5.0).displayName('Multiblock')
	    .entity(builder => {
	        builder.ticker((level, pos, state, be) => { // tick me here, but ONLY WHEN MULTIBLOCK IS FORMED!!
                
        	})
        	.pattern(() => { // ordering is: [aisle: z, aisle contents[]: y, single string: x]
        	    return BlockPatternBuilder.start()
        	        .aisle( 'BBB',
                            'ACA',
                            'AAA')
                    .aisle( 'BBB',
                            'AAA',
                            'AAA')
                    .aisle( 'BBB',
                            'AAA',
                            'AAA')
                    .where('A', BlockInWorld.or(BlockInWorld.hasState(BlockPredicate.forBlock('minecraft:iron_block')), BlockInWorld.hasBlockEntity(CAP_PREDICATE)))
              					// ^ iron block OR any capability on a BE
                    .where('C', BlockInWorld.hasState(BlockPredicate.forBlock('kubejs:multi_block')))
              					// ^ controller block
                    .where('B', BlockInWorld.hasState(BlockPredicate.forBlock('minecraft:copper_block')))
              					// ^ self explanatory
        	})
        })
        .property(BlockProperties.HORIZONTAL_FACING) // block builder stuff, facing direction
        .defaultState(state => {
            state.setValue(BlockProperties.HORIZONTAL_FACING, Direction.NORTH)
        })
        .placementState(state => {
            state.setValue(BlockProperties.HORIZONTAL_FACING, state.horizontalDirection.opposite)
        })
})
```

<p class="callout warning">currently only 1 input &amp; 1 output per type are set as the multiblock's IO, and it's the last one found in the scan.</p>

extra valid methods on `multiblock` builder:

- `pattern(builder => ...)`

available static methods in `BlockInWorld`:

- `hasState(predicate => ... return boolean)`
- `hasBlockEntity(predicate => ... return boolean)`
- `or(predicate1, predicate2)`
- `and(predicate1, predicate2)`

more advanced example: [link](https://gist.github.com/screret/2aa4e6f793123af67d854d6214cc8439 "beJs & ScreenJS advanced example")

multiblock (and recipe type) example: [link](https://gist.github.com/screret/e4b95c65da3960d9740f95cde6406f08 "link to multiblock example")

#### Recipe Types

beJS can create custom recipe types for your block entities to use!

```javascript
StartupEvents.registry('recipe_type', event => {
    event.create('name_here')
        .assembler((recipe, container) => { // optional, but very much suggested
            let results = recipe.results
            for (let i = 0; i < results.size() && i < container.containerSize; ++i) {
                container.setItem(i, results.get(i))
            }
        })
        .maxInputs(2) // required
        .maxOutputs(4) // required
        .toastSymbol('kubejs:block_id_here') // optional
})
```

valid methods on all RecipeType builders:

- `assembler((recipe, container) => ...)`
- `maxInputs(count)`
- `maxOutputs(count)`
- `toastSymbol(stack)`

#### Item/Fluid Handlers

beJS has multiple custom handlers that have extra functionality:

##### IMultipleItemHandler

IMultipleItemHandler is an item handler with multiple slots. valid methods listed below:

- `getAllContainers() : List<IItemHandlerModifiable>`
- `getContainer(index) : IItemHandlerModifiable`
- `getStackInSlot(container, slot) : ItemStack`
- `insertItem(container, slot, stack, simulate) : ItemStack`
- `extractItem(container, slot, amount, simulate) : ItemStack`
- `getSlotLimit(container, slot) : int`
- `isItemValid(container, slot, stack) : boolean`
- `setStackInSlot(container, slot, stack)`

##### IMultipleFluidHandler

IMultipleItemHandler is a fluid handler with multiple slots. valid methods listed below:

- default forge IFluidHandler methods (not listed here)
- `fill(tank, fluidStack, action) : int`
- `drain(tank, fluidStack, action) : FluidStack`
- `drain(tank, maxDrain, action) : FluidStack`

# ScreenJS

Download: [CurseForge](https://www.curseforge.com/minecraft/mc-mods/screenjs)

<p class="callout info">The custom ContainerMenu event is a startup event.</p>

Custom Container menus are created in a startup script. They cannot be reloaded without restarting the game. The event is not cancellable.

for block entities:

```javascript
StartupEvents.registry('menu', event => {
    event.create('example_block' /*name can be anything*/, 'block_entity')
        .addSlot(-10, -10) // adds a slot into this x,y position on the texture
        .addSlot(10, 200)
        .loop(builder /*this builder*/=> {
            for(let x = 0; x < 9; x++) {
                for (let y = 0; y < 4; y++) {
                    builder.addSlot(x * 18 /*<- the width of a slot, remember to add this*/, y * 18, x + y * 4, 0)
                }
            }
        })
        .addOutputSlot(118, 118, 0, 0, 1, 'minecraft:smelting') // adds a slot you can't put an item into, but can pull an item from
  																// LAST PARAMETER CAN BE NULL FOR NO OUTPUT HANDLING
  		.inputSlotIndices(0) // sets a list of ITEM HANDLER indexes to handle as slotChanged callback input
        .playerInventoryY(100) // marks the start of the player's inventory on the texture
        .tintColor(0xFF00FF00) // a color to tint the whole inventory texture, in hexadecimal [a, r, g, b]
        .progressDrawable(50, 50, new Rectangle(0, 0, 10, 30), 'forge:textures/white.png', 'up', 'energy') // displays an energy bar from the blockentity's FE capability
  		.slotChanged((menu, level, player, itemHandlers) => {
      		console.info('' + player)
    	})
  
        .setBlockEntity('kubejs:example_block') // the block entity type that should open this GUI on right-click
})
```

for any block:

```javascript
StartupEvents.registry('menu', event => {
    event.create('grass_block' /*name can be anything*/, 'block')
        /*default parameter set*/
  		.addItemHandler(9) // adds an item handler.
  		.addItemHandler(1)
  		.inputSlotIndices(0)
        .setBlock('minecraft:grass_block') // the block that should open this GUI on right-click
})
```

for entities:

```javascript
StartupEvents.registry('menu', event => {
    event.create('snow_golem' /*name can be anything*/, 'entity')
        /*default parameter set*/
        .setEntity('minecraft:snow_golem') // the enity type that should open this GUI on right-click
})
```

and lastly, for completely separate 'basic' GUIs:

```javascript
StartupEvents.registry('menu', event => {
    event.create('name_here' /*name can be anything*/)
        /*default parameter set*/
})
```

valid menu types:

- basic (this is the default)
- block\_entity
- block
- entity

methods the menu builder supports:

- `addSlot(x, y, slotIndex, containerIndex)`
- `addOutputSlot(x, y, slotIndex, inputContainerIndex, outputContainerIndex, recipeType)`
- `loop(builder => ...)`
- `inputSlotIndices(int[] indexes)`
- `tintColor(color)`
- `drawable(screenX, screenY, rectangle, textureLocation)`
- `progressDrawable(x, y, rectangle, textureLocation, direction, type)`
- `fluidDrawable(x, y, rectangle, textureLocation, direction, tankIndex)`
- `customDrawable(x, y, rectangle, textureLocation, direction, (menu, screen, drawable, direction) => ...)`
- `backroundTexture(texture, rectangle)`
- `quickMoveFunc((player, slotIndex, menu) => ... return item)`
- `slotChanged((menu, level, player, itemHandler) => ...)`
- `validityFunc((player, pos) => ... return boolean)`
- `disablePlayerInventory()`
- `playerInventoryY(yPos)`
- `button(rectangle, textComponent, button => ...)`

default available types:

- PROGRESS
- FUEL
- ENERGY

default available move directions:

- UP
- DOWN
- LEFT
- RIGHT

available types:

- `Rectangle(x, y, u ,v)`
- `MenuUtils` (contains `progress(max, current, length)` for custom bars)
- `RecipeWrapper` (forge `IItemHandlerModifiable` wrapper for recipes)
- `CraftingWrapper` (ScreenJS wrapper class used for `crafting` recipes)

#### Custom Key Binds

ScreenJS can do custom key bindings! examples &amp; available methods below:

<p class="callout info">The custom KeyBind event is a Client event.</p>

```javascript
// client_scripts

KeybindEvents.register(event => {
    event.register(new KeyBind("open_menu" /* name */, InputConstants.KEY_G /* key index, opengl spec */, "screenjs" /* category name */), (action, modifiers /* modifiers as per OpenGL spec */) => {
        if (action == 1) { // action == 1 is PRESS
            Minecraft.instance.gui.setOverlayMessage(Text.string('AAA').yellow(), false) // vanilla method
            MenuScreens.create('kubejs:separate', Minecraft.instance, 1000, Text.string('AAA').yellow()) // opens a GUI container, preferably of type 'basic'
        } else if (action == 0) { // action == 0 is RELEASE
            Minecraft.instance.gui.setOverlayMessage(Text.string('BBB').yellow(), true)
        } else { // action == 2 is REPEAT (after a second of PRESS)
            Minecraft.instance.gui.setOverlayMessage(Text.string('REPEAT').red(), false)
        }
    })
})
```

available methods:

- `register`

available types:

- `KeyBind(name, keyIndex, category)`
- `KeyAction(action, modifiers)`
- `InputConstants`
- `Minecraft` (client main class)
- 

# KubeJS REI Runtime

Download: [Curseforge](https://www.curseforge.com/minecraft/mc-mods/kubejs-rei-runtime) [Modrinth](https://modrinth.com/mod/kubejs-rei-runtime)

KubeJS REI Runtime lets you show/hide items in REI dynamically, it provides these methods by default:

```javascript
// in client_scripts

REIRuntime.showItem(item); // shows an item in REI
REIRuntime.showItems([item, item, ...]); // shows items in REI
REIRuntime.hideItem(item); // hides an item in REI
REIRuntime.hideItems([item, item, ...]); // hides items in REI
```

# KubeJS Botany Pots

Download:[ Curseforge](https://www.curseforge.com/minecraft/mc-mods/kubejs-botany-pots) [Modrinth](https://modrinth.com/mod/kubejs-botany-pots)

This mod allows you to create crops, soils, and fertilizers for the [Botany Pots](https://www.curseforge.com/minecraft/mc-mods/botany-pots) mod.

```javascript
ServerEvents.recipes(event => {
    event.recipes.botanypots.crop(
        "minecraft:candle", // seed item
        ["oak_leaves"], // categories that this crop can be planted on
        { block: "minecraft:candle" }, // display block
        [
            Item.of ("minecraft:candle") // item
                .withChance(100) // weight of this entry compared to the others
                .withRolls(1, 2) // the times this loot will be chosen (min, max)
            // for example, when chosen this will give 1 to 2 candles
        ],
        10, // growthTicks
        1, // optional, growthModifier - this can be set to 1 in most cases
    )

    event.recipes.botanypots.soil(
        "minecraft:oak_leaves", // the item that this soil is attached to
        { block: "minecraft:oak_leaves" }, // display block
        ["oak_leaves"], // categories that this soil provides
        100, // growth ticks that this soil will provide, set to -1 for no modifier
        0.5 // optional, growth modifier, example: 0.5 means all crops will take half the time
    )

    event.recipes.botanypots.fertilizer(
        "minecraft:iron_ingot", // fertilizer item
        10, // min growth ticks applied
        20 // max growth ticks applied
        // ex: 10 to 20 ticks will be randomly given to the crop
    )
})

// fired everytime a crop grows
BotanyPotsEvents.onCropGrow(event => {
    // event.random : the random object associated with the event
    // event.crop : a crop object describing the crop grown
    // event.originalDrops : an array of items this crop drops
    // event.drops : a writable array that changes the drops of the crop
    console.log([event.random, event.crop, event.originalDrops, event.drops].join(","))
})
```

# KubeJS Ars Nouveau

Download: [Curseforge](https://www.curseforge.com/minecraft/mc-mods/kubejs-ars-nouveau), [Modrinth](https://modrinth.com/mod/kubejs-ars-nouveau)

This addon allows you to create recipes for the mod [Ars Nouveau](https://www.curseforge.com/minecraft/mc-mods/ars-nouveau)

```javascript
ServerEvents.recipes(event => {
	event.recipes.ars_nouveau.enchanting_apparatus(
        [
            "minecraft:sand",
            "minecraft:sand",
            "minecraft:sand",
            "minecraft:sand",
        ], // input items
	    "minecraft:gunpowder", // reagent
	    "minecraft:tnt", // output
	    1000, // source cost
	    // true // keep nbt of reagent, think like a smithing recipe
	);

	event.recipes.ars_nouveau.enchantment(
        [
            "minecraft:sand",
            "minecraft:sand",
            "minecraft:sand",
            "minecraft:sand",
        ], // input items
        "minecraft:vanishing_curse", // applied enchantment
        1, // enchantment level
        1000, // source cost
    );

	event.recipes.ars_nouveau.crush(
        "minecraft:tnt", // input block
        [
            Item.of("minecraft:sand").withChance(1.0),
//            { item: Item.of("minecraft:sand").withChance(1.0), maxRolls: 4 }
        ] // loot table
        // true // drop the item in world?
    );

    /*
    // this *does* work, but the recipe must be a valid glyph
    // in the tome, so this really can only be used to
    // replace a glyph's recipe
    event.recipes.ars_nouveau.glyph(
        "minecraft:tnt", // output item (glyph)
        [
            "minecraft:sand",
            "minecraft:gunpowder",
        ], // input items
        3 // exp cost
    );
    */

    // accessible via `/ars-tome id` in this case `/ars-tome kubejs:not_glow`
    event.recipes.ars_nouveau.caster_tome(
        "Not-Glow Trap", // name,
        [
            "ars_nouveau:glyph_touch",
            "ars_nouveau:glyph_rune",
            "ars_nouveau:glyph_snare",
            "ars_nouveau:glyph_extend_time",
            "ars_nouveau:glyph_light"
        ], //spell
        "Doesn't snare the target and grant other targets Glowing.", // description
        16718260, // color
        {
            "family": "ars_nouveau:default",
            "pitch": 1.0,
            "volume": 1.0
        },
    ).id("kubejs:not_glow")

    event.recipes.ars_nouveau.imbuement(
        "minecraft:sand", // input item
        "minecraft:tnt", // output
        1000, // source cost
        []
    )

    event.recipes.ars_nouveau.imbuement(
        "minecraft:red_sand", // input item
        "minecraft:tnt", // output
        1000, // source cost
        []
    )
})
```

# KubeJS ProjectE

Download: [Curseforge](https://www.curseforge.com/minecraft/mc-mods/kubejs-projecte), [Modrinth](https://modrinth.com/mod/kubejs-projecte)

Lets you set the EMC values of items and the Philosopher's Stone transformations blocks with the [ProjectE](https://beta.curseforge.com/minecraft/mc-mods/projecte) mod. Examples are shown below.

Server side events ( `server_scripts` ):

```javascript
ProjectEEvents.setEMC(event => {
    // sets the absolute emc value of an item
    event.setEMC("minecraft:cobblestone", 0) // alias. setEMCAfter

    // sets the emc of an item before anything else happens
    // this can sometimes result in this emc value not being
    // set, but also it allows for emc values to be generated
    // from this one; i.e crafting recipes
    event.setEMCBefore("minecraft:stick", 10000);
})

ItemEvents.rightClicked("minecraft:stick", event => {
    let player = event.player;

    // getPlayerEMC will always return a string
    // because emc values can get very large
    player.tell("Your emc is " + ProjectE.getPlayerEMC(player))

    ProjectE.addPlayerEMC(player, 1000);
    // the second argument can be a string because of the above
    // ProjectE.setPlayerEMC also exists

    player.tell("Your new emc is " + ProjectE.getPlayerEMC(player))
})

```

Startup events ( `server_scripts` ):

```javascript
ProjectEEvents.registerWorldTransmutations(event => {
    event.transform("minecraft:tnt", "minecraft:oak_planks");
})
```

# KubeJS Powah

Download: [Curseforge](https://www.curseforge.com/minecraft/mc-mods/kubejs-powah) [Modrinth](https://modrinth.com/mod/kubejs-powah)

Allows you to create Energizing Orb recipes from the [Powah](https://beta.curseforge.com/minecraft/mc-mods/powah-rearchitected) mod.

Example:

```javascript
ServerEvents.recipes(event => {
    // .energizing([inputs, ...], output, energy)
	event.recipes.powah.energizing(["minecraft:cobblestone"], "minecraft:tnt", 1000)
})

PowahEvents.registerCoolants(event => {
    // .addFluid(fluid, coolness)
	event.addFluid("minecraft:lava", 10);
    
    // .addSolid(fluid, coolness)
	event.addSolid("minecraft:cobblestone", 10);
})

PowahEvents.registerHeatSource(event => {
    // .add(block, hotness)
	event.add("minecraft:cobblestone", 10);
})

PowahEvents.registerMagmaticFluid(event => {
    // .add(fluid, hotness)
	event.add("minecraft:water", 10);
})

```

# KJSPKG

**[KJSPKG](https://github.com/Modern-Modpacks/kjspkg)** is a package manager for KubeJS that can allow you to download different example scripts and libraries into your instance. It will automatically manage minecraft version, modloader, dependency and incompatibility control. It works with KubeJS 6 (1.19), KubeJS Legacy (1.16/1.18) and should even work with some pre-legacy versions (1.12)!

[![kjspkgbig.png](https://wiki.latvian.dev/uploads/images/gallery/2023-07/Dzs8ZXTbGkOwtmWf-kjspkgbig.png)](https://wiki.latvian.dev/uploads/images/gallery/2023-04/kOqnnW5AOQwxfiPO-kjspkgbig.png)

#### Installation

1. Download either the [CLI version of KJSPKG](https://github.com/Modern-Modpacks/kjspkg/tree/main#installation--update) or the [WIP GUI client](https://github.com/Modern-Modpacks/kjspkg-gui).
2. Open a terminal in the `kubejs` directory inside of your instance.
3. Run `kjspkg init` and select your minecraft version/modloader.

Now you are able to install packages into your instance.

#### Usage

- To download a package, run `kjspkg install <package_name>`
- To remove a package, run `kjspkg remove <package_name>`
- To search for a package, run `kjspkg search <query>`
- To list all packages in your instance, run `kjspkg list`
- To list all of the commands available, run `kjspkg help`

#### Adding your own package

If you have an example script you would like to share on KJSPKG, check out [the "Adding your own package" section](https://github.com/Modern-Modpacks/kjspkg#adding-your-own-package) of KJSPKG's README. We are always happy to add more scripts from different authors to our list!

#### Notable packages

##### **[`more-recipe-types`](https://kjspkglookup.modernmodpacks.site/#more-recipe-types)** (Legacy, 1.16.5/1.18.2, Forge/Fabric)

This package simplifies the process of adding recipes to custom machines from different mods without downloading any addons. For example, this bit of code will add a recipe transforming a stick and an iron ingot to [Powah](https://www.curseforge.com/minecraft/mc-mods/powah)'s Energizing Orb:

```javascript
onEvent('recipes', event => {
	global.mrt.powah.energizing(event, "minecraft:gold_ingot", ["minecraft:stick", "minecraft:iron_ingot"], 1000);
})
```

For other types, check out the [README file on GitHub](https://github.com/gcatkjspkgs/kubejs-more-recipe-types/blob/main/README.md).

##### `<strong class="mr-2 flex-self-stretch"><a data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" href="https://kjspkglookup.modernmodpacks.site/#create-depot-crafting">create-depot-crafting</a></strong>` (Legacy, 1.18.2, Fabric)

This package allows you to add custom recipes that use manual combination on the create depot. Example from the README:

```javascript
onEvent('block.right_click', event => {
    global.recipes.create.manual_depot_application(event,
        // Output
        Item.of('expandeddelight:cheese_sandwich'),
        // Inputs
        Ingredient.of('minecraft:bread'), // On depot
        Ingredient.of('expandeddelight:cheese_slice') // In hand
    )
});
```

Showcase:

[![68747470733a2f2f692e6962622e636f2f426e59505671572f6578616d706c652d6d696e2e676966.gif](https://wiki.latvian.dev/uploads/images/gallery/2023-04/cT0JKE97LRUTTcgy-68747470733a2f2f692e6962622e636f2f426e59505671572f6578616d706c652d6d696e2e676966.gif)](https://wiki.latvian.dev/uploads/images/gallery/2023-04/cT0JKE97LRUTTcgy-68747470733a2f2f692e6962622e636f2f426e59505671572f6578616d706c652d6d696e2e676966.gif)

If you're looking for a Forge port of this package, checkout **`<a href="https://kjspkglookup.modernmodpacks.site/#create-depot-crafting-forge">create-depot-crafting-forge</a>`**. A lot of the times KJSPKG's packages' names end in `-6` if they are a port of a different package for KubeJS 6 (1.19), and end in `-<modloader>` if they are a port of another package for a different modloader as per naming convention.

##### `<strong class="mr-2 flex-self-stretch"><a data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" href="https://kjspkglookup.modernmodpacks.site/#soljs">soljs</a></strong>` (KubeJS 6, 1.19.2, Forge/Fabric)

This package ports the mechanics of the [1.12.2 version of The Spice of Life mod](https://www.curseforge.com/minecraft/mc-mods/the-spice-of-life) to 1.19 using only KubeJS. It works like a standalone mod and does not require any configuration. Depends on [AppleSkin](https://www.curseforge.com/minecraft/mc-mods/appleskin).

# KubeJS Offline Documentation

## Dynamic Documentation in a single html page.

Download: [Curseforge](https://www.curseforge.com/minecraft/mc-mods/kubejs-offline), [Modrinth](https://modrinth.com/mod/kubejs-offline)

KubeJS Offline is a mod that dumps all class data at runtime into a single html file using a single command. `/kubejs\_offline`.

### Preview Generated Documentation Pages:

[1.19.2 Forge ](https://hunter19823.github.io/kubejsoffline/1.19.2/forge)[1.19.2 Fabric](https://hunter19823.github.io/kubejsoffline/1.19.2/fabric)

[1.18.2 Forge ](https://hunter19823.github.io/kubejsoffline/1.18.2/forge)[1.18.2 Fabric](https://hunter19823.github.io/kubejsoffline/1.18.2/fabric)

[Enigmatica 9](https://hunter19823.github.io/kubejsoffline/modpacks/engimatica9)

### How does it work?

When you execute the KubeJS Offline command, a scan of the Java runtime is performed to find what classes exist at that time. This is important as mods might provide new event classes and possibly new methods to existing Minecraft classes.

After the mod has searched what classes exist and are available at that time, it then proceeds to compress that data down into a json object.

It records everything from the full class name, package info, super classes, sub-classes, generic implementations, fields, methods, as well as their relationships to other classes.

This data is then used to create an html page which then runs dependency-less JavaScript to generate the webpage html elements.

You can then open the file in a modern web browser, no need to host it on a server or anything like that.

### Additional Features:

You can right click inside the webpage to toggle certain tables, private fields, and other info that you may not need.

There is a search feature you can activate by adding a question mark to the end of the url.  
An example of this search is:

[https://hunter19823.github.io/kubejsoffline/1.19.2/forge#any--EventJS](https://hunter19823.github.io/kubejsoffline/1.19.2/forge#any--EventJS)

# KubeJS Farmers Delight

Download: [Curseforge](https://www.curseforge.com/minecraft/mc-mods/kubejs-delight)

Example:

Startup Scripts:

```javascript
StartupEvents.registry("block", event => {
  event.create('example_pie', 'farmersdelight:pie')
    .sliceItem('kubejs:example_pie_slice')
    .displayName('Example Pie')
  event.create('example_feast', 'farmersdelight:feast')
    .servingsAmount(3)
    .servingItems(['kubejs:example_feast_serving', 'kubejs:example_feast_serving_2'])
    .displayName('Example Feast')
})

StartupEvents.registry("item", event => {
  event.create('example_knife', 'farmersdelight:knife')
    .displayName('Example Knife')
    .tier('diamond')
})
```

Server Scripts:

```javascript
ServerEvents.recipes(event => {
	event.recipes.farmersdelight.cutting(
        "minecraft:cobblestone",
        "#forge:tools/pickaxes", // tool
        [ // results
            "minecraft:iron_ore",
            Item.of("minecraft:diamond")
                .withChance(0.1)
        ],
        // "" // sound
	);

	event.recipes.farmersdelight.cooking(
	    ["minecraft:cobblestone"],
	    "minecraft:iron_ore", // output
	    30, // exp
	    10, // cookTime
	    "minecraft:bowl", // container
	);
})
```

# KubeJS Industrial Foregoing

Download: [Curseforge](https://curseforge.com/minecraft/mc-mods/kubejs-industrial-foregoing/)

This lets you modify and create various recipes for [Industrial Foregoing](https://www.curseforge.com/minecraft/mc-mods/industrial-foregoing)

```javascript
ServerEvents.recipes(event => {
    event.recipes.industrialforegoing.dissolution_chamber(
        ["minecraft:tnt"], // input items
        "minecraft:water", // input fluid
        "minecraft:sand", // output item
        100 // time
    )
//     .outputFluid("minecraft:water"); // output fluid

    event.recipes.industrialforegoing.fluid_extractor(
        "minecraft:tnt", // input block
        "minecraft:sand", // output block
        0.5, // break chance
        "minecraft:lava" // output fluid
    )

    event.recipes.industrialforegoing.stonework_generate(
        "minecraft:tnt",
        100, // water needed
        100, // lava needed
        50, // water consumed
        50 // lava consumed
    )
    event.recipes.industrialforegoing.crusher( // the pickaxe action in the stonework factory
        "minecraft:tnt", // input item
        "minecraft:sand" // output item
    )

    event.recipes.industrialforegoing.laser_drill_ore(
        "minecraft:tnt", // output
        "minecraft:sand",  // catalyst
        [ //rarity, see below for more details
            {
                "blacklist": {
                    "type": "minecraft:worldgen/biome",
                    "values": [
                        "minecraft:the_end",
                        "minecraft:the_void",
                        "minecraft:small_end_islands",
                        "minecraft:end_barrens",
                        "minecraft:end_highlands",
                        "minecraft:end_midlands"
                    ]
                },
                "depth_max": 16,
                "depth_min": 5,
                "weight": 4,
                "whitelist": {}
            },
            {
                "blacklist": {
                    "type": "minecraft:worldgen/biome",
                    "values": [
                        "minecraft:the_end",
                        "minecraft:the_void",
                        "minecraft:small_end_islands",
                        "minecraft:end_barrens",
                        "minecraft:end_highlands",
                        "minecraft:end_midlands"
                    ]
                },
                "depth_max": 255,
                "depth_min": 0,
                "weight": 1,
                "whitelist": {}
            }
        ]
    )

    event.recipes.industrialforegoing.laser_drill_fluid(
        "minecraft:water", // output
        "minecraft:sand", // catalyst
        [ // rarity, see wiki for more details
            {
                "blacklist": {
                    "type": "minecraft:worldgen/biome",
                    "values": [
                        "minecraft:the_end",
                        "minecraft:the_void",
                        "minecraft:small_end_islands",
                        "minecraft:end_barrens",
                        "minecraft:end_highlands",
                        "minecraft:end_midlands"
                    ]
                },
                "depth_max": 16,
                "depth_min": 5,
                "weight": 4,
                "whitelist": {}
            },
            {
                "blacklist": {
                    "type": "minecraft:worldgen/biome",
                    "values": [
                        "minecraft:the_end",
                        "minecraft:the_void",
                        "minecraft:small_end_islands",
                        "minecraft:end_barrens",
                        "minecraft:end_highlands",
                        "minecraft:end_midlands"
                    ]
                },
                "depth_max": 255,
                "depth_min": 0,
                "weight": 1,
                "whitelist": {}
            }
        ],
        "minecraft:zombie" // entity required below
    )
})

```