As usual we have some breaking changes along with a Minecraft release. In this case the changes are centered around the new dynamic Enchantment registry, and some further tweaks to dynamic registries as we refine support for those.
The (I think) most notable change to existing logic is a change to how dynamic registry values are named. Historically they keep their namespace ID inside themselves (eg Biome#namespace
). These methods are now gone, instead, the ID is set while registering the object.
// Old
DimensionType helloWorld = DimensionType.builder("hello:world").build();
helloWorld.namespace(); // "hello:world"
DynamicRegistry.Key<DimensionType> helloWorldKey = MinecraftServer.getDimensionTypeRegistry().register(helloWorld);
// New
DimensionType helloWorld = DimensionType.builder().build();
helloWorld.namespace(); // Error: Method does not exist.
DynamicRegistry.Key<DimensionType> helloWorldKey = MinecraftServer.getDimensionTypeRegistry().register("hello:world", helloWorld);
In addition, all registry entries now have a DataPack
associated with them (or the null DataPack
). Currently only DataPack.MINECRAFT_CORE
and null
are valid packs, and you cannot create your own. The only use of data packs right now is to decide whether or not registry entries are ‘known’ to the client. For example, the vanilla plains biome is registered like:
biomeRegistry.register("minecraft:plains", plainsBiomeObject, DataPack.MINECRAFT_CORE);
The result is that the server will assume the client has the same plains definition, so will skip sending it in the registry data packet. Adding your own entries or reassigning existing ones should never assign DataPack.MINECRAFT_CORE
in synced registries. There are some use cases for ‘server-side’ registries described below in ‘Enchantments’.
Enchantments, Painting Variants, and Jukebox Songs are now dynamic registries driven by the server. As with all other dynamic registries, the vanilla data is loaded automatically.
Enchantments have a complicated definition structure as well as a lot of server-driven behavior. The vast majority of this behavior is not implemented by Minestom beyond defining the data structures.
You should read the 24w18a snapshot notes here: https://www.minecraft.net/en-us/article/minecraft-snapshot-24w18a#effect-components, but I will describe the basics of enchantments as they are currently implemented in Minestom. I would like to note that this entire system is experimental and subject to change as we refine how server driven content is managed in Minestom.
The following types are used to define enchantments:
LevelBasedValue
is the lowest primitive for computing a value in an enchantment. It takes in the enchantment level and computes some floating point output value. For example5f
,level * 2f
,{1f, 3f, 4f}[level-1]
. Mojang defines (and the client understands)constant
,linear
,clamped
,fraction
,levels_squared
,lookup
. The implementations are inLevelBasedValue
. These are all implemented correctly in Minestom.Enchantment.Effect
s are the behavior functions of enchantments. There are multiple types of effect:ValueEffect
s perform some operation on a base value, for example to apply an attribute. Mojang defines (and the client understands)add
,all_of
,multiply
,remove_binomial
,set
. The implementations are inValueEffect
. These are all implemented correctly in Minestom.AttributeEffect
applies an attribute modifier. Minestom does not currently apply the attribute modifier to the entity using the enchantment.EntityEffect
s perform operations on Entities related to the enchanted item usage. Mojang defines (and the client understands)all_of
,apply_mob_effect
,damage_entity
,damage_item
,explode
,ignite
,play_sound
,replace_block
,replace_disk
,run_function
,set_block_properties
,spawn_particles
,summon_entity
. Minestom includes parsers for many of these (lossless noop parsers for the rest). None of the behavior is implemented for these, nor do they share a common API currently (see below).LocationEffect
s are the union of allEntityEffect
s andAttributeEffect
. The full list for reference isall_of
,attribute
,apply_mob_effect
,damage_entity
,damage_item
,explode
,ignite
,play_sound
,replace_block
,replace_disk
,run_function
,set_block_properties
,spawn_particles
,summon_entity
.ConditionalEffect
andTargetedConditionalEffect
wraps an effect and an optionalDataPredicate
TODO WHAT DOES THIS API LOOK LIKE TODO TODO TODODamageImmunityEffect
is a singleton with no data. It can be applied conditionally in the associated component.
EffectComponent
s areDataComponent
s (likeItemComponent
), applied to enchantment definitions. They apply combinations of the aboveEffect
s. Minestom defines the vanilla effect component types.
Minestom comes with an empty definition (which does not lose data loading the vanilla entries), a complete type definition, or a full implementation of all of the Mojang definitions above.
This API will be completed/fleshed out in future updates, but for now it is possible to send enchantments to the client and interpret the effects server side. In the future, we are planning to support registration of custom server-side effects, as well as likely an API for propagating/using effects as expected.
The most common use case for an enchantment in Minestom is most likely registering an enchantment with an empty effect map which will show the name on the item but nothing else, and then handling the effects server side. This case is completely supported right now.
ExecutionType.SYNC
andASYNC
are removed (were deprecated).START_TICK
is the replacement forSYNC
,ASYNC
does not have a replacement, you should use the JVM facilities for executing logic off the tick threads.- It is now invalid to register an entry to a
DynamicRegistry
after the server has been started. This is generally an unsafe behavior because a client may have been sent the old registry content and will be kicked if they receive a reference to an unknown or differing registry entry. To disable this check, you can set theminestom.registry.late-register
system property. DynamicRegistry
can now hold other objects besides justProtocolObject
s, and can be instantiated without NBT for use as server-only registries.DynamicRegistry#create(String)
is still marked asApiStatus.Internal
because it may change in the future. This annotation will likely be removed in the next update.ArgumentEnchantment
(andArgumentType.Enchantment
) are gone, as enchantments are now a server driven registry, ArgumentResource (ArgumentType.Resource
) should be used for client prediction of enchantments.DataComponent
containers now have an overload for settingDataComponent<Unit>
values without passingUnit.INSTANCE
. For example,itemStack.with(ItemComponent. HIDE_TOOLTIP)
.ItemComponent
type definitions can be fetched by their ID usingItemComponent#fromNamespaceId
now, instead ofDataComponent#fromNamespaceId
like in 1.20.6.DataComponentMap.Builder
has been partially split off intoDataComponentMap.PatchBuilder
when being used to build a component patch.AttributeSlot
has been renamed toEquipmentSlotGroup
.MAINHAND
andOFFHAND
have been renamed toMAIN_HAND
andOFF_HAND
to match other usages in Minestom.- Along with the protocol change, attributes no longer have a UUID anywhere, and now use a namespace id to identify themselves.
- A handful of places now use
DynamicRegistry.Key<Enchantment>
:EnchantmentTableInventory
EnchantmentList
ItemComponent.FOOD
now hasItemStack usingConvertsTo
.ItemComponent.JUKEBOX_PLAYABLE
was added.- New packets for custom report details (
CustomReportDetailsPacket
) and server links (ServerLinksPacket
).
- Receiving transfers and correctly processing entity passenger/vehicle offsets remains as a TODO item from 1.20.6. You can read more about that change in the previous update notes.
- Game tags (not the Tag nbt wrapper) are in need of a rework.