Repository navigation
Addon Development
English | 简体中文
KineticCore gives addon mods one API for GUI, F6 configuration, networking and compression, input and lifecycle events, hooks, command extensions, selectors, registry access and Minecraft helpers. Addons call only the public dev.xyat.kineticcore.api.*; internal/ is an implementation detail and may change at any time.
- Download the JAR that matches the addon's target version from Releases:
kineticcore-<loader>-<minecraft>-<version>.jar. - Add it to the build as a mod dependency (ModDevGradle Legacy
modImplementationfor Forge 1.20.1,implementationfor NeoForge), and declare thekineticcoredependency inmods.toml/neoforge.mods.toml. - Each Minecraft version of an addon uses the KineticCore JAR of the same version; never mix them.
Use a matching compiler toolchain and Java release target for each addon node: Java 17 for Forge 1.20.1, Java 21 for NeoForge 1.21.1, and Java 25 for NeoForge 26.1.2. KineticCore uses the same matrix; its Gradle daemon runs separately on Java 21.
The public API is documented in the source Javadoc. Running gradlew buildJavaDOC in the KineticCore repository writes javadoc/index.html and a shareable archive to the project root.
Controls are created on the KineticUi passed to build(KineticUi ui).
| I need | Use |
|---|---|
| A screen |
extends KineticPage + build(KineticUi ui); open it with KineticGui.open(page) or, from another page, openChild(page)
|
| A container menu screen |
extends KineticContainerPage<M> + KineticClientMenus.register(...); the menu type comes from KineticMenuTypes
|
| A button |
ui.button(x, y, w), .compact() for the narrow style; ui.itemButton(...) for an item icon button |
| An on/off switch | ui.toggle(...) |
| Text input |
ui.textField(...), multi-line ui.textArea(...)
|
| Number input (integer or decimal, min/max, negatives) | ui.numberField(...) |
| Input with suggestions |
ui.autoComplete(...), for numbers ui.numberAutoComplete(...)
|
| A choice |
ui.dropdown(...), ui.cycleButton(...) or ui.slider(...)
|
| A colour |
ui.colorButton(...) / ui.colorSwatch(...); picker KineticSelectors.openColorPicker(...)
|
| Tabs |
ui.tabBar(...) (fixed) or ui.tabStrip(...) (scrollable) |
| A list of text rows | ui.selectionList(...) |
| Items as a list or a grid |
ui.itemSelectionList(...) / ui.itemGrid(...)
|
| Rows with trailing buttons or toggles |
ui.actionList, ui.itemActionList, ui.multiActionList, ui.toggleList, ui.toggleActionList, ui.multiToggleList
|
| Rows the page draws itself |
KineticRowList<T>, added with ui.add(...)
|
| Rows of real controls that scroll together | ui.scrollViewport(...) |
| A control the API does not have | first check whether it is generic and belongs in the API; otherwise KineticCustomControl + ui.add(...)
|
| Confirm dialog, right-click menu, tooltip | page openDialog(...), openContextMenu(...) with KineticOverlays.MenuItem, builder .tooltip(...) or page showTooltip(...)
|
| Pick an item, entity, NBT or colour | KineticSelectors.open* |
| Let players move a HUD element | KineticHudEditorPage |
| Draw on the HUD | KineticClientEvents.onHudRender(...) |
| Draw icons or custom rows in an item tooltip |
KineticItemTooltips.registerComponentFactory(...) with a KineticTooltipComponent
|
| Add a button to a vanilla or third-party screen | KineticClientEvents.onScreenInitAfter(...) |
| Drawing, theme colours, text width |
KineticGraphics, KineticTheme, KineticText
|
| Labels that follow world positions (name tags, damage numbers) |
KineticWorldRender.beginScreenOverlay(context) inside KineticClientEvents.onLevelRender(...)
|
| Secondary (muted) text |
KineticTheme.muted(text); never the gray §7 / §8 codes |
| Input text cyan while unchanged, green once edited | builder .defaultText(...) / .defaultValue(...), or .firstShownTextAsDefault() when the value is loaded after building |
| Player-visible text |
KineticI18n.translatable(...) with keys in zh_cn and en_us
|
| An F6 config page |
KTConfigPage.builder(...) + KTConfigApi.register(...); server-owned values KTServerConfigSpec. If the client shows or uses server-managed values (tooltips, client effects), add .mirrorOnJoin() so each player loads them from the server on joining instead of using the local file; do not broadcast config edits to all players |
| Network packets |
PacketChannel (or KineticNetwork.channel(...)); compression KineticCompression
|
| Commands |
KineticCommands (sub-commands under /kt); clickable help lines CommandText.suggest(...)
|
| Clickable chat text | CommandText.clickToRun / clickToSuggest / clickToCopy / clickToOpenUrl |
| Key bindings |
KineticKeyBindings; gestures such as double taps KineticInputGestures
|
| Client and server events |
KineticClientEvents, KineticServerEvents, KineticWorldEvents, KineticLivingEvents
|
| Client or server side, config folder |
KineticPlatform; config files KineticPaths
|
| Registries and IDs |
KineticRegistries, KineticResourceIds; registration KineticItems, KineticMenuTypes, KineticEntityTypes
|
| Flight permission | KineticFlightSources |
| Player pose, crawling |
KineticPlayerPose, KineticCrawling
|
| Force-loading chunks | KineticChunkLoading |
| Shared injection points |
ClientHooks, CommonHooks, ServerHooks
|
Before adding API: first try a new parameter on an existing builder or interface, then a combination of existing controls. A new API type is only worth it for a new interaction that an unrelated addon could use unchanged.
- One mod should not have several Mixins for the same capability.
- An injection that an unrelated addon could reuse as it is belongs in KineticCore's public API or hooks.
- A Mixin that only serves one addon's own gameplay stays in that addon.
- Do not reimplement GUI, input, config, networking or other capabilities the public API already provides.
The API is the same on every version except where Minecraft itself changed.
From 1.21.1
- Item text (
KineticItemText) follows that version's/givesyntax, see Item Text Syntax. -
KineticClientAdvancements.all()returnsList<AdvancementHolder>. -
KineticEnchantments.registeris not available: enchantments come from data pack JSON. - Networking uses NeoForge payloads; the
KineticNetworkAPI is unchanged.
26.1.2
- Key binding categories are ids:
KineticKeyBindings.Builder.category(ResourceLocation). Categories outside theminecraftnamespace are registered automatically; their name comes from the language keykey.category.<namespace>.<path>. - Item model properties belong to model JSON: register them with
KineticItemProperties.registerRange(id, codec)andregisterConditional(id, codec), and refer to them fromrange_dispatch/conditionmodels. - Villager trades are data-driven;
KineticVillagerEventsis not available. - Spawn handlers reserve a place for first logins with
ServerHooks.prepareFreshLogin(...); 26.1 creates the player object itself.
gradle/kinetic-addon-architecture.gradle from the KineticCore repository can be copied into an addon and applied with apply from, so that addon code going around the GUI API fails to compile. gradle/kinetic-addon-reobf-verification.gradle checks the reobfuscated JAR of 1.20.1 addons. The rules are explained in the GUI API Guide.