Note: If you are a script developer (i.e. pack dev, server admin, etc.), you likely want to visit our website or the wiki instead.
(For a Table Of Contents, click the menu icon in the top left!)
KubeJS is a multi-modloader Minecraft mod which lets you create scripts in the JavaScript programming language to manage your server using events, change recipes, add and edit (coming soon!) loot tables, customise your world generation, add new blocks and items, or use custom integration with other mods like FTB Quests for even more advanced features!
If you think you've found a bug with the mod or want to ask for a new feature, feel free to open an issue here on GitHub, we'll try to get on it as soon as we can! Alternatively, you can also discuss your feature requests and suggestions with others using the Discussions tab.
And if you're just looking for help with KubeJS overall and the wiki didn't have the answer for what you were looking for, you can join our Discord server and ask for help in the support channels, as well!
KubeJS is distributed under the GNU Lesser General Public License v3.0, or LGPLv3. See our LICENSE file for more information.
Creating addon mods for KubeJS is easy! Just follow the following steps to your own liking, depending on how deep you want your integration to go!
To add a Gradle dependency on KubeJS, you will need to add the following repositories to your build.gradle
's repositories
:
repositories {
maven {
// Shedaniel's maven (Architectury API)
url = "https://maven.architectury.dev"
content {
includeGroup "dev.architectury"
}
}
maven {
// saps.dev Maven (KubeJS and Rhino)
url = "https://maven.saps.dev/minecraft"
content {
includeGroup "dev.latvian.mods"
}
}
}
You can then declare KubeJS as a regular compile
-time dependency in your dependencies
block:
// Loom (Fabric / Quilt / Architectury)
modImplementation("dev.latvian.mods:kubejs-<loader>:${kubejs_version}")
// ForgeGradle
implementation fg.deobf("dev.latvian.mods:kubejs-forge:${kubejs_version}")
// these two are unfortunately needed since fg.deobf doesn't respect transitive dependencies yet
implementation fg.deobf("dev.latvian.mods:rhino:${rhino_version}")
implementation fg.deobf("dev.architectury:architectury-forge:${architectury_version}")
Just set the versions with most up-to-date version of the required mod(s), which you also find using these badges:
(Note: The above badges may not represent the true latest version of these mods. As a basic rule of thumb, for KubeJS and Rhino, you should always be using the latest version compiled against your version of Minecraft, for example 1802.+
for Minecraft 1.18.2, while for Architectury, the corresponding major version will be provided. You can also click on the badge to see all versions of each mod)
You should of course use kubejs-forge
for Forge projects and kubejs-fabric
for Fabric projects. KubeJS' dependencies (notably, Rhino and Architectury) should all be downloaded automatically; otherwise, you may need to add them manually.
KubeJS uses the official mappings for Minecraft ("mojmap"). Since the refmap remapper for Mixins on ModLauncher currently doesn't support non-MCP mappings, you will need to add some extra lines to your runs to keep it from crashing, as detailed here on the Mixin issue tracker. Be sure to regenerate your runs afterwards!
minecraft {
runs {
client {
property 'mixin.env.remapRefMap', 'true'
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
}
// should be analogue for any other runs you have
}
}
KubeJS plugins are a new feature introduced in KubeJS 1605.3.7
designed to ease the process of adding KubeJS integration to mods. They contain convenient hooks for addon developers to:
- perform certain actions during or after plugin initialisation (
init
/afterInit
- Example) - add custom recipe handlers for modded recipe types (
addRecipes
- Example) (this replacesRegisterRecipeHandlersEvent
listeners) - add classes to the class filter (with the option to add to the filter for a certain script type only, as well as to add
Class
objects directly rather than using strings) (addClasses
- Example) - add global bindings (
addBindings
- Example) (this replacesBindingsEvent
listeners) - add type wrappers for automatic native type conversion, for example to allow
String
s to be automatically converted toResourceLocation
s. (addTypeWrappers
- Example) - attach data to players, worlds or the server that may then be used by script makers (
attach(Player|World|Server)Data
- Example, please note this example currently uses the deprecated way of listening toAttachPlayerDataEvent
itself)
To add custom recipe handlers for your own modded recipe types, use KubeJS plugins as noted above. A concrete example of this can be found here for integration with the Thermal series, but we'll give you a simple outline of the process here as well:
public class MyExamplePlugin extends KubeJSPlugin {
// for custom recipe types based on shaped recipes, like non-mirrored or copying NBT
event.registerShaped("mymod:shapedbutbetter"); // analogue: registerShapeless
// this is what you usually want to use for custom machine recipe types and the like
event.register("mymod:customtype", MyRecipeJS::new);
}
public class MyRecipeJS extends RecipeJS {
// Input is an IngredientStackJS, return value should be the
// serialised JSON variant used in your recipe
@Override
public JsonElement serializeIngredientStack(IngredientStackJS stack);
// say your recipe had processing time, you would use builder
// methods like these to add these properties to the JSON
public MyRecipeJS time(int ticks) {
json.addProperty("time", ticks);
save();
return this;
}
// Similar to inputs, if you use custom parsing to determine your
// result item, use this method to override the parsing of said item.
@Override
public ItemStackJS parseResultItem(@Nullable Object o) {
if(o instanceof JsonObject) {
// parse the item yourself if it's a JsonObject
}
return super.parseResultItem(o); // fallback to default parsing otherwise
}
}
Similarly to adding custom recipe types, you may also add custom bindings to KubeJS (see AntimatterAPI for a simple example). Bindings can be anything from single value constants to Java class and method wrappers, and can be constrained to individual scopes, contexts and script types, as well!
KubeJS offers native Java type access in script files, meaning that basic Java types can be referenced directly by using for example java("package.class")
. This access is by default limited to only specifically allowed classes, with the default setting being to deny anything else unless explicitly specified by the user, however you may still want to explicitly allow (or explicitly deny, to prevent users from using it even with the above setting toggled on) access to certain classes in your mod. To do this, you may either provide a class filter using a KubeJS plugin (more on that later!) or you can avoid adding KubeJS as a dependency entirely by providing a simple kubejs.classfilter.txt
file in your mod's resources
with the following format (Note that comments aren't allowed in the actual file):
+mymod.api.MyModAPI // This will *explicitly allow* your class to be used in KubeJS
-mymod.internal.HttpUtil // This will *explicitly deny* your class from being used in KubeJS
For any unset classes, the default setting is once again determined by the user.
If you want to contribute to KubeJS, you will first need to set up a development environment, which should be fairly simple. Just clone the repository using Git:
git clone https://github.com/KubeJS-Mods/KubeJS.git
and import the gradle project using an IDE of your choice! (Note: Eclipse may have some problems with Architectury's runs, but IDEA and VS Code should work fine.)
Building KubeJS from source should be rather straightforward, as well, just run gradlew build
in the root project, and the corresponding jars for Forge and Fabric should be in the respective module's build/libs
directory (kubejs-<loader>-<version>.jar
). The project will also produce a common jar; that one however should not be used in production.
When creating a pull request to KubeJS, please make sure you acknowledge the following:
- We will usually not accept pull requests that add mod-specific support; those things are better suited as KubeJS plugins (optimally within the target mods themselves) or integration mods.
- Please be sure to test your feature before creating a pull request. We are a rather small team and as such, can't spend all too much time on reviewing pull requests.
- While not strictly required, please try to adhere by the repository's code style and conventions. A sample
.editorconfig
file exists to make this even easier for you to achieve (see the relevant EditorConfig plugin for your IDE) - If you are unsure whether your feature fits into KubeJS and would like to hear additional opinions on the matter, feel free to open an
issue
or adiscussion
to discuss it further with us first!