Skip to content

Instantly share code, notes, and snippets.

@mworzala
Created June 13, 2024 15:59
Show Gist options
  • Save mworzala/4052eec3561caa86b69908214682936f to your computer and use it in GitHub Desktop.
Save mworzala/4052eec3561caa86b69908214682936f to your computer and use it in GitHub Desktop.

Minestom 1.21

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.

Dynamic Registry Changes

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’.

Data-driven Content

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

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 example 5f, level * 2f, {1f, 3f, 4f}[level-1]. Mojang defines (and the client understands) constant, linear, clamped, fraction, levels_squared, lookup. The implementations are in LevelBasedValue. These are all implemented correctly in Minestom.
  • Enchantment.Effects are the behavior functions of enchantments. There are multiple types of effect:
    • ValueEffects 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 in ValueEffect. 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.
    • EntityEffects 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).
    • LocationEffects are the union of all EntityEffects and AttributeEffect. The full list for reference is all_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 and TargetedConditionalEffect wraps an effect and an optional DataPredicate TODO WHAT DOES THIS API LOOK LIKE TODO TODO TODO
    • DamageImmunityEffect is a singleton with no data. It can be applied conditionally in the associated component.
  • EffectComponents are DataComponents (like ItemComponent), applied to enchantment definitions. They apply combinations of the above Effects. 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.

Misc Changes

  • ExecutionType.SYNC and ASYNC are removed (were deprecated). START_TICK is the replacement for SYNC, 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 the minestom.registry.late-register system property.
  • DynamicRegistry can now hold other objects besides just ProtocolObjects, and can be instantiated without NBT for use as server-only registries. DynamicRegistry#create(String) is still marked as ApiStatus.Internal because it may change in the future. This annotation will likely be removed in the next update.
  • ArgumentEnchantment (and ArgumentType.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 setting DataComponent<Unit> values without passing Unit.INSTANCE. For example, itemStack.with(ItemComponent. HIDE_TOOLTIP).
  • ItemComponent type definitions can be fetched by their ID using ItemComponent#fromNamespaceId now, instead of DataComponent#fromNamespaceId like in 1.20.6.
  • DataComponentMap.Builder has been partially split off into DataComponentMap.PatchBuilder when being used to build a component patch.
  • AttributeSlot has been renamed to EquipmentSlotGroup. MAINHAND and OFFHAND have been renamed to MAIN_HAND and OFF_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 has ItemStack usingConvertsTo.
  • ItemComponent.JUKEBOX_PLAYABLE was added.
  • New packets for custom report details (CustomReportDetailsPacket) and server links (ServerLinksPacket).

Misc Future Tasks

  • 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment