Migration Guide 0.24 ➝ 0.25¶
Item and Block Types¶
Nova items and blocks now use Bukkit's ItemType and BlockType, just like vanilla types.
Replace Material-Based Type Access
ItemStack.type and Block.type return a Material, which cannot represent Nova's custom types. Use these extension properties provided by Nova instead:
ItemStack.itemType: ItemTypegets an item stack's type.Block.blockType: BlockTypegets a block's type.
Both work for vanilla and Nova types. Update existing type checks too, so they do not mistake custom items or blocks for vanilla ones.
Nova now includes a Kotlin compiler plugin that warns about Material usage and other common migration mistakes. Nova's Gradle plugin enables it automatically.
Registries¶
Registration functions now return a RegistryEntry, a reference to the registered object, instead of the object itself. Keep this reference in your registration singleton. If a function needs the actual object, call entry.get() after the registry has loaded.
Do not resolve entries while initializing your registration singleton: the objects have not been created yet. Builder functions run later and may run again during registry reloads.
When comparing types, compare entries with entries or resolved values with values. Nova's ItemStack.itemTypeEntry: RegistryEntry.Paper<ItemType> extension property returns the entry for an item stack:
Configs¶
Configs are now read through ConfigProvider instead of Configurate's configuration nodes. Files remain YAML, but values are deserialized using kotlinx.serialization. See Accessing Configs.
If you have custom Configurate serializers, replace them with KSerializers and register them via CONFIGS.setSerializers(addon, serializersModule). See Custom Serializers.
Calling entry("path") without a default value is deprecated because a missing or invalid config value can throw an exception at runtime and break addon functionality. Pass a default with entry(default, "path") so Nova can fall back to it instead.
Behavior Factories¶
For ItemBehaviorFactory:
For BlockBehaviorFactory:
Item Behaviors¶
- Replace
vanillaMaterialPropertieswith an override of modifyClientSideItemType that selects the client-sideItemType. handleUseTickandhandleUseStoppednow returnItemAction?. Returnnullto skip cooldowns and other post-use effects. ReturnItemAction.Noneto trigger those effects without changing the stack, or anotherItemActionto also modify the stack.
Built-In Behaviors¶
- The Enchantable factory takes registry entry sets, e.g.
supportedEnchantments = registryEntrySetOf(EnchantmentEntries.SHARPNESS), instead of providers of enchantment sets. Damageable.repairIngredientnow takes a registry entry set instead of aRecipeChoice, e.g.registryEntrySetOf(ItemTypeEntries.IRON_INGOT).- Add
AttributeModifiers()explicitly if your item uses theattribute_modifiersconfig entry.
Item Data¶
NamespacedCompound and the ItemStack.novaCompound extension property have been removed. Item data is now stored in Bukkit's persistent data container (PDC).
Existing Item Data Is Migrated Automatically
Nova automatically merges data from old item compounds into the item's PDC, keeping the same namespaced keys. You do not need to write a converter for this storage change.
Nova's item-data helper functions now read and write PDC values using CBF serialization. ItemBehavior.defaultCompound has also been removed, so supply defaults when reading missing values:
Tools and Weapons¶
Tool now controls mining through vanilla tool rules. Attack damage, attack speed, sweeping attacks, and durability loss on attack are handled by Weapon. Add it to tools that previously relied on Tool for these settings:
Move durability loss on block breaking from Damageable to Tool, and durability loss on attacking from Damageable to Weapon.
Custom Tool Categories¶
ToolCategory objects are no longer registered. Pass the category's name as a Key to Tool instead. Nova uses that name to find tags, which are named groups of items or blocks.
To migrate a category named example_addon:hammer, create two tags:
- A block tag,
example_addon:mineable/hammer, containing the blocks that hammers should mine efficiently. - An item tag,
example_addon:hammers, for the hammer items.Tooladds its items to this tag automatically, but the tag must already be registered.
Custom Tool Tiers¶
ToolTier registration and the numeric tier hierarchy in tool_levels.yml have been removed. Tiers are now identified by a Key, and block tags determine which blocks each tier is too weak to collect drops from.
For a tier named example_addon:emerald, this tag is example_addon:incorrect_for_emerald_tool. Put blocks in it if their drops should require a stronger tool than emerald.
For an existing emerald tier equivalent to diamond, reuse diamond's restrictions:
The tool_tier: example_addon:emerald config setting can stay the same; it now selects the tier's block tag by name.
When configuring the tier in Kotlin:
behaviors(Tool(toolTier = Key.key(ExampleAddon, "emerald")))
See Custom Tool Categories and Tiers for the tag setup, or Tool Behavior for explicit rules and the tool_rules config format.
Blocks¶
BlockPos has been replaced by Bukkit's Block throughout the addon API.
Block access no longer goes through WorldDataManager. Nova provides these extension properties on Bukkit's Block:
Block.blockType: BlockTypereturns the block's type, whether vanilla or custom.Block.novaBlockState: NovaBlockState?returns the custom block's state, ornullfor a vanilla block.Block.novaTileEntity: TileEntity?returns the Nova tile-entity at that block, ornullif there is none.
Block Registration¶
Move breaking properties and sounds out of the behavior list and configure them directly in the block builder:
The TileEntityLimited block behavior has been removed; tile-entity limit tracking is now enabled by default.
The stateSelector passed to entityBacked, entityItemBacked, or modelLess must now return Bukkit BlockData instead of an NMS block state. For example, return BlockType.BARRIER.createBlockData() for a barrier backing block.
Block State Properties¶
The split between scoped and unscoped block state properties has been removed. Specify allowed values when creating the property:
Use DefaultBlockStateProperties for built-in properties. The function that chooses a property's value when a block is placed is now an Autofiller; read placement parameters with ctx.resolve(...) instead of ctx[...].
The Waterloggable behavior has been removed. Keep the DefaultBlockStateProperties.WATERLOGGED property; it now enables waterlogging on its own.
Block States¶
Block States Are Now Mutable
NovaBlockState now implements Bukkit's BlockData. Changing a property modifies the existing state object instead of creating a different one. This does not update the block in the world automatically.
Outside a tile-entity, apply the state with block.blockData = state. Inside a tile-entity:
Block Contexts¶
Block parameters now use Bukkit types. BLOCK_POS is replaced by BLOCK, and the separate vanilla / Nova type and state parameters are replaced by BLOCK_TYPE (BlockType) and BLOCK_STATE (BlockData).
Contexts¶
Context autofillers now run when build() is called, instead of lazily when a parameter is read.
Custom Parameter Registration¶
Custom parameter types are now registered on the intention itself:
For optional or required parameters, use addOptionalParamType or addRequiredParamType, respectively.
Tile Entities¶
Tile-entity constructors now receive a Bukkit Block, and the pos property is now block:
TileEntity.coroutineSupervisor is now nullable instead of lateinit.
Tile Entity Networks¶
In network side configurations, replace Map<BlockFace, ...> with CubeFaceMap and Map<BlockSide, ...> with BlockSideMap (likewise CubeFaceSet / BlockSideSet for sets).
For custom network types, replace holderTypes with extractHolders. Nova calls this function with a NetworkEndPoint. Return the data holders your network needs from that end point, such as its ItemHolder, or null if a required holder is missing. Pass an Int for tickDelay instead of a provider.
GUIs¶
InvUI's reactive Kotlin DSL is now preferred over the previous builder-based approach with manual GUI updates. All Nova functions built around this DSL now use items that expect a GUI texture to provide the background, instead of items with the inventory background built into their textures.
Client-side items are no longer directly exposed to addons. Use regular server-side item stacks and item providers, including in GUIs.
Replace item.model.clientsideProvider with item.guiItemProvider for GUI icons. guiItemProvider only differs from itemProvider by hiding Nova's advanced tooltip; it does not create a separate client-side item.
EnergyBar, FluidBar, and direct SideConfigMenu construction are deprecated in favor of energyBar, fluidBar, and openSideConfigItem.
GUI Textures¶
Update existing GUI texture registrations like this:
getTitle now returns a Provider<Component> instead of a Component:
Tile Entity Menus¶
Replace annotated inner menu classes with an overridden menu property:
Each player gets their own window. If your menu opens additional windows, call menu.register(window) so Nova can close them when the tile-entity is removed or the player moves out of range. See Tile Entity Menu.
Recipes¶
Register custom recipe types during PRE_WORLD instead of POST_WORLD. See Creating a custom Recipe Type.
Packet Entities¶
Fake entities have been replaced by packet entities:
Notable Dependency Updates¶
- Minecraft:
26.2➝26.3 - InvUI:
2.2.0➝2.5.1 - commons-provider:
2.0.0-alpha.10➝2.0.0-alpha.11