This is a high level, non-exhaustive overview on how to migrate your mod from 1.20.5/6 to 1.21. This does not look at any specific mod loader, just the changes to the vanilla classes.
This primer is licensed under the Creative Commons Attribution 4.0 International, so feel free to use it as a reference and leave a link so that other readers can consume the primer.
If there's any incorrect or missing information, please leave a comment below. Thanks!
There are a number of user-facing changes that are part of vanilla which are not discussed below that may be relevant to modders. You can find a list of them on Misode's version changelog.
All experimental features which were disabled with the update_1_21 flag are now moved to their proper locations and implementations. Removed features flags can be seen within net.minecraft.world.level.storage.WorldData#getRemovedFeatureFlags.
The ResourceLocation is final and its constructor is private. There are alternatives depending on your usecase:
new ResourceLocation(String, String)->fromNamespaceAndPath(String, String)new ResourceLocation(String)->parse(String)new ResourceLocation("minecraft", String)->withDefaultNamespace(String)of->bySeparatorisValidResourceLocationis removed
Plural references to the block, entity type, fluid, game event, and item tags have been removed. They should now use their exact registry name. The same goes for registry folders.
tags/blocks->tags/blocktags/entity_types->tags/entity_typetags/fluids->tags/fluidtags/game_events->tags/game_eventtags/items->tags/itemadvancements->advancementrecipes->recipestructures->structure'loot_tables->loot_table
There have been a number of rendering changes. While this will not be an in-depth overview, it will cover most of the surface-level changes.
The vertex system has received a major overhaul, almost being completely rewritten. However, most of the codebase has some analogue to its previous version in different locations.
First, a VertexConsumer is obtained using one of two methods: from a MultiBufferSource or the Tesselator. Both essentially take a ByteBufferBuilder, which handles the direct allocation of the vertex information, and wrap it in a BufferBuilder, which writes the data to the ByteBufferBuilder while also keeping track of other settings needed to properly write the data, such as the VertexFormat.
The MultiBufferSource constructs a VertexConsumer via #getBuffer while Tesselator does so via Tesselator#begin.
// For some MultiBufferSource bufferSource
VertexConsumer buffer = bufferSource.getBuffer(RenderType.translucent());
// Note the different return types when using
// We will need the BufferBuilder subclass in the future
BufferBuilder buffer = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);Next, vertices are added to the VertexConsumer using the associated methods. #addVertex must always be called first, followed by the settings specified in the VertexFormat. #endVertex no longer exists and is called automatically when calling #addVertex or when uploading the buffer.
// For some VertexConsumer buffer
buffer.addVertex(0.0f, 0.0f, 2000.0f).setUv(0, 0).setColor(-1);
buffer.addVertex(0.0f, 1.0f, 2000.0f).setUv(0, 0).setColor(-1);
buffer.addVertex(1.0f, 1.0f, 2000.0f).setUv(0, 0).setColor(-1);
buffer.addVertex(1.0f, 0.0f, 2000.0f).setUv(0, 0).setColor(-1);Once the vertices are added, those using MultiBufferSource are done. MultiBufferSource will batch the buffers together for each RenderType and call the BufferUploader within the pipeline. If the RenderType sorts the vertices on upload, then it will do so when endBatch is called, right before RenderType#draw is called to setup the render state and draw the data.
The Tesselator, on the other hand, does not handle this logic as you are creating the BufferBuilder instance to manage. In this case, after writing all ther vertices, BufferUploader#drawWithShader should be called. The MeshData provided, which contains the vertex and index buffer along with the draw state, can be built via BufferBuilder#buildOrThrow. This replaces BufferBuilder#end.
// For some BufferBuilder buffer
BufferUploader.drawWithShader(buffer.buildOrThrow());com.mojang.blaze3d.vertex.DefaultVertexFormat'sVertexFormatElements have been moved toVertexFormatElement.com.mojang.blaze3d.vertex.BufferBuilder$RenderedBuffer->MeshDatacom.mojang.blaze3d.vertex.VertexConsumervertex->addVertex- Overload with
PoseStack$Pose, Vector3f
- Overload with
color->setColoruv->setUvoverlayCoords->setUv1,setOverlayuv2->setUv2,setLightnormal->setNormalendVertexis removeddefaultColor,color->setColor,setWhiteAlpha
net.minecraft.client.model.Model#renderToBuffernow takes in an integer representing the ARGB tint instead of four floats- There is also a final method which passes in no tint
net.minecraft.client.model.geom.ModelPart#render,$Cube#compilenow takes in an integer representing the ARGB tint instead of four floats- There is also an overloaded method which passes in no tint
net.minecraft.client.particle.ParticleRenderType#begin(Tesselator, TextureManager),end->begin(BufferBuilder, TextureManager)- This method returns the
BufferBuilderrather than void - When
null, no rendering will occur
- This method returns the
- Shader removals and replacements
minecraft:position_color_tex->minecraft:position_tex_colorminecraft:rendertype_armor_glint->minecraft:rendertype_armor_entity_glintminecraft:rendertype_glint_direct->minecraft:rendertype_glint
net.minecraft.client.renderer.MultiBufferSource- All
BufferBuilders have been replaced withByteBufferBuilder immediateWithBuffersnow takes in aSequencedMap
- All
net.minecraft.client.renderer.RenderTypeend->drawsortOnUpload- When true, sorts the quads according to theVertexSortingmethod for theRenderType
net.minecraft.client.renderer.SectionBufferBuilderPack#builder->#buffernet.minecraft.client.renderer.ShaderInstanceno longer can change the blend mode, onlyEffectInstancecan, which is applied forPostPasssetDefaultUniforms- Sets the default uniforms accessible to all shader instances
net.minecraft.client.renderer.entity.ItemRenderergetArmorFoilBufferno longer takes in a boolean to change the render typegetCompassFoilBufferDirectis removed
net.minecraft.client.renderer.entity.layers.RenderLayer#coloredCutoutModelCopyLayerRender,renderColoredCutoutModeltakes in an integer representing the color rather than three floatscom.mojang.blaze3d.vertex.BufferVertexConsumeris removedcom.mojang.blaze3d.vertex.DefaultedVertexConsumeris removed
net.minecraft.client.renderer.chunk.RenderRegionCache#createRegiononly takes in theSectionPosnow instead of computing the section from theBlockPosnet.minecraft.client.renderer.chunk.SectionCompiler- Renders the given chunk region via#compile. Returns the results of the rendering compilation.- This is used within
SectionRenderDispatchernow to pass around the stored results and upload them
- This is used within
Enchantments are now a datapack registry object. Querying them requires access to a HolderLookup.Provider or one of its subclasses.
All references to Enchantments are now wrapped with Holders. Some helpers can be found within EnchantmentHelper.
{
// A component containing the description of the enchantment
// Typically will be a component with translatable contents
"description": {
"translate": "enchantment.minecraft.example"
},
// An item tag that holds all items this enchantment can be applied to
"supported_items": "#minecraft:enchantable/weapon",
// An item tag that holds a subset of supported_items that this enchantment can be applied to in an enchanting table
"primary_items": "#minecraft:enchantable/sharp_weapon",
// A non-negative integer that provides a weight to be added to a pool when trying to get a random enchantment
"weight": 3,
// A non-negative integer that indicates the maximum level of the enchantment
"max_level": 4,
// The minimum cost necessary to apply this enchantment to an item
"min_cost": {
// The base cost of the enchantment at level 1
"base": 10,
// The amount to increase the cost with each added level
"per_level_above_first": 20
},
// The maxmimum cost required to apply this enchantment to an item
"max_cost": {
"base": 60,
"per_level_above_first": 20
}
// A non-negative integer that determines the cost to add this enchantment via the anvil
"anvil_cost": 5,
// The equipment slot groups this enchantment is applied to
// Can be 'any', 'hand' ('mainhand' and 'offhand'), 'armor' ('head', 'chest', 'legs', and 'feet'), or 'body'
"slots": [
"hand"
],
// An enchantment tag that contains tags that this enchantment cannot be on the same item with
"exclusive_set": "#minecraft:exclusive_set/damage",
// An encoded data component map which contains the effects to apply
"effects": {
// Read below
},
}EnchantmentEffectComponents essentially apply how enchantments should react in a given context when on an item. Each effect component is encoded as an object with its component id as the key and the object value within the effect list, usually wrapped as a list. Most of these components are wrapped in a ConditionalEffect, so that will be the focus of this primer.
ConditionalEffects are basically a pair of the effect to apply and a list of loot conditions to determine when to execute the enchantment. The codec provided contains the effect object code and the loot context param sets to apply for the conditions (commonly one of the ENCHANTED_* sets).
Each effect object has its own combination of codecable objects and abstract logic which may refer to other registered types, similiar to loot conditions, functions, number providers, etc. For enchantments currently, this means enchantments which are applied directly to the entity, scaled and calulated for some numerical distribution, applied to the blocks around the entity, or calculating a number for some information.
For example, all protection enchantments use almost the exact same effect objects (minecraft:attributes and minecraft:damage_protection) but use the conditions to differentiate when those values should be applied.
To apply these enchantments, EnchantmentHelper has a bunch of different methods to help with the application. Typically, most of these are funneled through one of the runIterationOn* methods. These method take in the current context (e.g., stack, slot, entity) and a visitor which holds the current enchantment, level, and optionally the stack context if the item is in use. The visitor takes in a mutable object which holds the final value to return. The modifications to apply to the given item(s) are within Enchantment#modify*. If the conditions match, then the value from the mutable object is passed in, processed, and set back to the object.
EnchantmentProviders are a provider of enchantments to items for entity inventory items or for custom loot on death. Each provider is some number of enchantments that is then randomly selected from and applied to the specified stacks via EnchantmentHelper#enchantItemFromProvider which takes in the stack to enchant, the registry access, the provider key, the difficulty instance, and the random instance.
net.minecraft.world.entity.LivingEntity#activeLocationDependentEnchantments- Returns the enchantments which depend on the current location of the entitynet.minecraft.world.entity.Entity#doEnchantDamageEffectshas been removednet.minecraft.world.entity.npc.VillagerTrades$ItemListingimplementations withEnchantments now take in keys or tags of the corresponding objectnet.minecraft.world.entity.player.Player#getEnchantedDamage- Gets the dmaage of a source modified by the current enchantmentsnet.minecraft.world.entity.projectile.AbstractArrow#hitBlockEnchantmentEffects- Applies the enchantment modifiers when a block is hitnet.minecraft.world.entity.projectile.AbstractArrow#setEnchantmentEffectsFromEntityhas been removednet.minecraft.world.item.ItemStack#enchanttakes in aHolder<Enchantment>instead of the direct objectnet.minecraft.world.entity.Mob#populateDefaultEquipmentEnchantments,enchantSpawnedWeapon,enchantSpawnedArmornow take in aServerLevelAccessorandDifficultyInstance
PaintingVariants are now a datapack registry object. Querying them requires access to a HolderLookup.Provider or one of its subclasses.
{
// A relative location pointing to 'assets/<namespace>/textures/painting/<path>.png
"asset_id": "minecraft:courbet",
// A value between 1-16 representing the number of blocks this variant takes up
// e.g. a width of 2 means it takes up 2 blocks, and has an image size of 32px
"width": 2,
// A value between 1-16 representing the number of blocks this variant takes up
// e.g. a height of 1 means it takes up 1 blocks, and has an image size of 16px
"height": 1
}AttributeModifiers no longer take in a String representing its UUID. Instead, a ResourceLocation is provided to uniquely identity the modifier to apply. Attribute modifiers can be compared for ResourceLocations using #is.
net.minecraft.world.effect.MobEffectaddAttributeModifier,$AttributeTemplatetakes in aResourceLocationinstead of aString
net.minecraft.world.entity.ai.attributes.AttributeInstancegetModifiersreturns aMap<ResourceLocation, AttributeModifier>getModifier,hasModifier,removeModifiernow takes in aResourceLocationremoveModifiernow returns a booleanremovePermanentModifieris removedaddOrReplacePermanentModifier- Adds or replaces the provided modifier
net.minecraft.world.entity.ai.attributes.AttributeMapgetModifierValue,hasModifier, now takes in aResourceLocation
net.minecraft.world.entity.ai.attributes.AttributeSuppliergetModifierValue,hasModifier, now takes in aResourceLocation
Recipes now take in a net.minecraft.world.item.crafting.RecipeInput instead of a Container. A RecipeInput is basically a minimal view into a list of available stacks. It contains three methods:
getItem- Returns the stack in the specified indexsize- The size of the backing listisEmpty- true if all stacks in the list are empty
As such, all implementations which previous took a Container now take in a RecipeInput. You can think of it as replacing all the C generics with a T generic representing the RecipeInput. This also includes RecipeHolder, RecipeManager, and the others below.
CraftingInput is an implementation of RecipeInput which takes in width and height of the grid along with a list of ItemStacks. One can be created using CraftingInput#of. These are used in crafting recipes.
SingleRecipeInput is an implementation of RecipeInput that only has one item. One can be created using the constructor.
How entities change dimensions have been slightly reworked in the logic provided. Instead of providing a PortalInfo to be constructed, instead everything returns a DimensionTransition. DimensionTransition contains the level to change to, the entity's position, speed, and rotation, and whether a respawn block should be checked. DimensionTransition replaces PortalInfo in all scenarios.
Entities have two methods for determining whether they can teleport. Entity#canUsePortal returns true if the entity can use a Portal to change dimensions, where the boolean supplies allows entities who are passengers to teleport. To actually change dimensions, Entity#canChangeDimensions must return true, where the current and teleporting to level is provided. Normally, only canUsePortal is changed while canChangeDimensions is always true.
canChangeDimensionsfunctioned ascanUsePortalin 1.20.5/6.
To change dimensions via a portal, a Portal should be supplied to Entity#setAsInsidePortal. A Portal contains how long it takes for the portal to transition, the DimensionTransition destination, and the transition effect to apply to the user. This is all wrapped in a PortalProcessor and stored on the Entity. Once the player is teleported a DimensionTransition$PostDimensionTransition is executed, for example playing a sound.
Portals are generally implmented on the Block doing the teleporting.
net.minecraft.world.entity.EntitychangeDimension(ServerLevel)->changeDimension(DimensionTransition)findDimensionEntryPoint->Portal#getPortalDestinationgetPortalWaitTime->Portal#getPortalTransitionTimehandleInsidePortal->setAsInsidePortalhandleNetherPortal->handlePortalteleportToWithTicketis removedgetRelativePortalPositionis now public
net.minecraft.world.level.portal.PortalShapecreatePortalInfois removedfindCollisionFreePositionis now public
net.minecraft.client.player.LocalPlayer#getActivePortalLocalTransition- Defines the transition to apply to the entity when the player is within a portalnet.minecraft.world.level.portal.PortalForce#findPortalAround->findClosestPortalPosition
net.minecraft.recipebook.ServerPlaceRecipenow has a generic taking in theRecipeInputand theReciperather than theContainernet.minecraft.world.inventory.CraftingContainer#asCraftInput- Converts a crafting container to an input to supplynet.minecraft.world.inventory.CraftingContainer#asPositionedCraftInput- Converts a crafting container to an input positioned at some location within a gridnet.minecraft.world.inventory.CraftingMenu#slotChangedCraftingGridnow takes in aRecipeHoldernet.minecraft.world.inventory.RecipeBookMenunow has a generic taking in theRecipeInputand theReciperather than theContainerbeginPlacingRecipe- When the recipe is about to be placed in the corresponding locationfinishPlacingRecipe- AFter the recipe has been placed in the corresponding location
net.minecraft.client.gui.screens.recipebook.*RecipeComponent#addItemToSlotstill exists but is no longer overridded from its subclass
The following is a list of useful or interesting additions, changes, and removals that do not deserve their own section in the primer.
The options screens within net.minecraft.client.gui.screens and net.minecraft.client.gui.screens.controls have been moved to net.minecraft.client.gui.screens.options and net.minecraft.client.gui.screens.options.controls, respectively.
net.minecraft.data.loot.LootTableProvider$SubProviderEntry takes in a function which provides the HolderLookup$Provider and returns the LootTableSubProvider. LootTableSubProvider#generate no longer takes in a HolderLookup$Provider as its first argument.
Registries#DECORATED_POT_PATTERNS takes in a DecoratedPotPattern instead of the raw string for the asset id. This change has been reflected in all subsequent classes (e.g. Sheets).
RecordItems has been removed in favor of a new data component JukeboxPlayable. This is added via the item properties. A jukebox song is played via JukeboxSongPlayer. JukeboxBlockEntity handles an implementation of JukeboxSongPlayer, replacing all of the logic handling within the class itself.
net.minecraft.world.item.Item$Properties#jukeboxPlayable- Sets the song to play in a jukebox when this is addednet.minecraft.world.item.JukeboxSong- ASoundEvent, description, length, and comparator output record indicating what this item would do when placed in a jukebox- This is a datapack registry
net.minecraft.world.item.JukeboxPlayable- The data component for aJukeboxSongnet.minecraft.world.item.JukeboxSongPlayer- A player which handles the logic of how a jukebox song is playednet.minecraft.world.level.block.entity.JukeboxBlockEntity#getComparatorOutput- Gets the comparator output of the song playing in the jukebox
Chunk generation has been reorganized again, where generation logic is moved into separate maps, task, and holder classes to be executed and handled asyncronously in most instances. Missing methods can be found in ChunkGenerationTask, GeneratingChunkMap, or GenerationChunkHolder. Additional chunk generation handling is within net.minecraft.world.level.chunk.status.*.
This also means some region methods which only contain generation-based information have been replaced with one of these three classes instead of their constructed counterparts. The steps are now listed in a ChunkPyramid, which determines the steps takes on how a protochunk is transformed into a full chunk. Each step can have a ChunkDependencies, forcing the order of which they execute. ChunkPyramid#GENERATION_PYRAMID handles chunk generation during worldgen while LOADING_PYRAMID handles loading a chunk that has already been generated. The WorldGenContext holds a reference to the main thread box when necessary.
net.minecraft.client.DeltaTracker is an interface mean to keep track of the delta ticks, both ingame and real time. This also holds the current partial tick. This replaces most instances passing around the delta time or current partial tick.
net.minecraft.client.Minecraft#getFrameTime,getDeltaFrameTime->getTimernet.minecraft.client.Timer->DeltaTracker$Timernet.minecraft.client.gui.Gui#rendernow takes in aDeltaTracker
com.mojang.realmsclient.dto.RealmsServer#isMinigameActive- Returns whether a minigame is active.net.minecraft.SystemReport#sizeInMiB- Converts a long representing the number of bytes into a float representing Mebibyte (Power 2 Megabyte)net.minecraft.Util#isSymmetrical- Checks whether a list, or some subset, is symmetricalnet.minecraft.advancements.critereon.MovementPredicate- A predicate which indicates how the entity is currently movingnet.minecraft.client.gui.components.AbstractSelectionList#clampScrollAmount- Clamps the current scroll amountnet.minecraft.client.gui.screens.AccessibilityOnboardingScreen#updateNarratorButton- Updates the narrator buttonnet.minecraft.client.gui.screens.worldselection.WorldCreationContext#validate- Validates the generators of all datapack dimensionsnet.minecraft.client.multiplayer.ClientPacketListenerupdateSearchTrees- Rebuilds the search trees for creative tabs and recipe collectionssearchTrees- Gets the current search trees for creative tabs and recipe collections
net.minecraft.client.multiplayer.SessionSearchTrees- The data contained for creative tabs and recipe collections on the clientnet.minecraft.commands.arguments.item.ItemParser$Visitor#visitRemovedComponent- Executed when a component is to be removed as part of an item inputnet.minecraft.core.Registry#getAny- Gets an element from the registry, usually the first one registerednet.minecraft.core.component.DataComponentMapmakeCodec- Creates a component map codec from a component type codecmakeCodecFromMap- Creates a component map codec from a component type to object map codec
net.minecraft.util.ProblemReporter#getReport- Returns a report of the problemnet.minecraft.util.Unit#CODECnet.minecraft.world.damagesource.DamageSources#campfire- Returns a source where the damage was from a campfirenet.minecraft.world.damagesource.DamageType#CODECnet.minecraft.world.entity.LivingEntityhasLandedInLiquid- Returns whether the entity is moving faster than -0.00001 in the y direction while in a liquidgetKnockback- Gets the knockback to apply to the entity
net.minecraft.world.entity.Mob#playAttackSound- Executes when the mob should play a sound when attackingnet.minecraft.world.entity.ai.attributes.Attribute#CODECnet.minecraft.world.entity.ai.attributes.AttibuteMapaddTransientAttributeModifiers- Adds all modifiers from the provided mapremoveAttributeModifiers- Removes all modifiers in the provided map
net.minecraft.world.entity.projectile.AbstractArrowgetWeaponItem- The weapon the arrow was fired fromsetBaseDamageFromMob- Sets the base damage this arrow can apply
net.minecraft.world.entity.projectile.Projectile#calculateHorizontalHurtKnockbackDirection- Returns the horizontal vector of the knockback directionnet.minecraft.world.inventory.ArmorSlot- A slot for armornet.minecraft.world.item.CrossbowItem#getChargingSounds- Sets the sounds to play when pulling back the crossbownet.minecraft.world.item.Item#postHurtEntity- Gets called after the enemy has been hurt by this itemnet.minecraft.world.level.Explosion#canTriggerBlocks- Returns whether the explosion cna trigger a blocknet.minecraft.world.level.block.LeverBlock#playSound- Plays the lever click soundnet.minecraft.world.level.levelgen.blockpredicates.BlockPredicateunobstructed- Returns a predicate which indicates the current vector is not obstructed by another entity
net.minecraft.world.level.storage.loot.functions.EnchantedCountIncreaseFunction- A function which grows the loot based on the corresponding enchantment levelnet.minecraft.world.level.storage.loot.predicates.EnchantmentActiveCheck- Checks whether a given enchantment is appliednet.minecraft.world.level.storage.loot.providers.number.EnchantmentLevelProvider- Determines the enchantment level to providenet.minecraft.world.phys.AABB#move- An overload of#movewhich takes in aVector3fnet.minecraft.core.dispenser.DefaultDispenseItemBehavior#consumeWithRemainder- Shrinks the first item stack. If empty, then the second item stack is returned. Otherwise, the second item stack is added to an inventory or dispensed, and the first item stack is returned.net.minecraft.server.MinecraftServerthrowIfFatalException- Throws an exception if its variable isn't nullsetFatalException- Sets the fatal exception to throw
net.minecraft.util.StaticCache2D- A two-dimensional read-only array which constructs all objects on initializationnet.minecraft.world.entity.EntityfudgePositionAfterSizeChange- Returns whether the entity's position can be moved to an appropriate free position after its dimension's changegetKnownMovement- Returns the current movement of the entity, or the last known client movement of the player
net.minecraft.world.entity.ai.attributes.AttributesetSentiment- Sets whether the attribute provides a positive, neutral or negative benefit when the value is positivegetStyle- Gets the chat formatting of the text based on the sentiment and whether the attribite value is positive
net.minecraft.world.entity.ai.attributes.AttributeMap#getAttributestoSync- Returns the attributes to sync to the clientnet.minecraft.world.level.storage.loot.LootContext$Builder#withOptionalRandomSource- Sets the random source to use for the loot context during generation- This is passed by
LootTable#getRandomItems(LootParams, RandomSource)
- This is passed by
net.minecraft.client.Options#genericValueOrOffLabel- Gets the generic value label, or an on/off component if the integer provided is 0net.minecraft.client.gui.GuiGraphics#drawStringWithBackdrop- Draws a string with a rectangle behind itnet.minecraft.gametest.framework.GameTestHelperassertBlockEntityData- Asserts that the block entity has the given informationassertEntityPosition- Asserts that the enity position is within a bounding box
net.minecraft.server.level.ServerPlayer#copyRespawnPosition- Copies the respawn position from another playernet.minecraft.server.players.PlayerList#sendActiveEffects,sendActivePlayerEffects- Sends the current entity's effects to the client using the provided packet listenernet.minecraft.util.Mth#hsvToArgb- Converts an HSV value with an alpha integer to ARGBnet.minecraft.world.entity.Entity#absRotateTo- Rotates the y and x of the entity clamped between its maximum valuesnet.minecraft.world.entity.ai.attributes.AttributeMap#assignBaseValues- Sets the base value for each attribute in the mapnet.minecraft.world.item.ItemStack#forEachModifier- An overload which applies the modifier for each equipment slot in the group- Applies to
net.minecraft.world.item.component.ItemAttributeModifiers#forEachas well
- Applies to
net.minecraft.world.level.levelgen.PositionalRandomFactory#fromSeed- Constructs a random instance from a seednet.minecraft.world.level.levelgen.structure.pools.DimensionPadding- The padding to apply above and below a structure when attempting to generatenet.minecraft.ReportType- An object that represents a header plus a list of nuggets to display after the header textnet.minecraft.advancements.critereon.GameTypePredicate- A predicate that checks the game type of the player (e.g. creative, survival, etc.)net.minecraft.advancements.critereon.ItemJukeboxPlayablePredicate- A predicate that checks if the jukebox is playing a songnet.minecraft.core.BlockPos#clampLocationWithin- Clamps the vector within the blocknet.minecraft.core.registries.RegistrieselementsDirPath- Gets the path of the registry keytagsDirPath- Gets the tags path of the registry key (replacesTagManager#getTagDir
net.minecraft.network.DisconnectionDetails- Information as to why the user was disconnected from the current worldnet.minecraft.server.MinecraftServer#serverLinks- A list of entries indicating what the link coming from the server is- Only used for bug reports
net.minecraft.util.FastColor$ABGR32#fromArgb32- Reformats an ARGB32 color into a ABGR32 color$ARGB32#average- Averages two colors together by each component
net.minecraft.util.Mth#lengthSquared- Returns the squared distance of three floatsnet.minecraft.world.entity.LivingEntity#triggerOnDeathMobEffects- Trigers the mob effects when an entity is killednet.minecraft.world.entity.TamableAnimaltryToTeleportToOwner- Attempts to teleport to the entity ownershouldTryTeleportToOwner- Returns true if the entity owner is more than 12 blocks awayunableToMoveToOwner- Returns true if the animal cannot move to the entity ownercanFlyToOwner- Returns true if the animal can fly to the owner
net.minecraft.world.entity.projectile.Projectile#disown- Removes the owner of the projectilenet.minecraft.world.item.EitherHolder- A holder which either contains the holder instance or a resource keynet.minecraft.world.level.chunk.ChunkAccess#isSectionEmpty- Returns whether the section only has airnet.minecraft.FileUtil#sanitizeName- Replaces all illegal file charcters with underscoresnet.minecraft.Util#parseAndValidateUntrustedUri- Returns a URI after validating that the protocol scheme is supportednet.minecraft.client.gui.screens.ConfirmLinkScreennow has two overloads to take in aURIconfirmLinkNowandconfirmLinkalso has overloads for aURIparameter
net.minecraft.client.renderer.LevelRenderer#renderFace- Renders a quad given two points and a colornet.minecraft.client.renderer.entity.EntityRenderer#renderLeash- A private method that renders the leash for an entitynet.minecraft.client.resources.model.BlockStateModelLoader- Loads the blockstate definitions for every block in the registry- Anything missing from
ModelBakeryis most likely here
- Anything missing from
net.minecraft.client.resources.model.ModelBakery$TextureGetter- Gets theTextureAtlasSpritegiven the model location and the material providednet.minecraft.core.BlockPos#getBottomCenter- Gets theVec3representing the bottom center of the positionnet.minecraft.gametest.framework.GameTestBatchFactory#fromGameTestInfo(int)- Batches the game tests into the specified partitionsnet.minecraft.gametest.framework.GameTestHelper#getTestRotation- Gets the rotation of the structure from the test infonet.minecraft.gametest.framework.GameTestRunner$StructureSpawner#onBatchStart- Executes when the batch is going to start running within the levelnet.minecraft.network.ProtocolInfo$Unboundid- The id of the protocolflow- The direction the packet should be sentlistPackets- Provides a visitor to all packets that can be sent on this protocol
net.minecraft.network.chat.Component#translationArg- Creates a component for aURInet.minecraft.network.protocol.game.VecDeltaCodec#getBase- Returns the base vector before encodingnet.minecraft.server.level.ServerEntitygetPositionBase- Returns the current position of the entitygetLastSentMovement- Gets the vector representing the last velocity of the entity sent to the clientgetLastSentXRot- Gets the last x rotation of the entity sent to the clientgetLastSentYRot- Gets the last y rotation of the entity sent to the clientgetLastSentYHeadRot- Gets the last y head rotation of the entity sent to the client
net.minecraft.world.damagesource.DamageSource#getWeaponItem- Returns the itemstack the direct entity hadnet.minecraft.world.entity.EntityadjustSpawnLocation- Returns the block pos representing the spawn location of the entity. By default, returns the entity spawn locationmoveTohas an overload taking in aVec3placePortalTicket- Adds a region ticket that there is a portal at theBlockPosgetPreciseBodyRotation- Lerps between the previous and current body rotation of the entitygetWeaponItem- The item the entity is holding as a weapon
net.minecraft.world.entity.Leashable- Indicates that an entity can be leashednet.minecraft.world.entity.MobdropPreservedEquipment- Drops the equipment the entity is wearing if it doesn't match the provided predicate or if the equipment succeeds on the drop chance check
net.minecraft.world.entity.player.PlayersetIgnoreFallDamageFromCurrentImpulse- Ignores the fall damage from the current impulses for 40 ticks when truetryResetCurrentImpulseContext- Resets the impulse if the grace time reaches 0
net.minecraft.world.item.ItemStack#hurtAndConvertOnBreak- Hurts the stack and when the item breaks, sets the item to another itemnet.minecraft.world.level.chunk.storage.ChunkIOErrorReporter- Handles error reporting for chunk IO failuresnet.minecraft.world.level.chunk.sotrage.ChunkStorage,IOWorker,RegionFileStorage,SimpleRegionStorage#storageInfo- Returns theRegionStorageInfoused to store the chunknet.minecraft.world.level.levelgen.structure.Structure$StructureSettingsnow has a constructor with default values given the biome tag$Builder- Builds the settings for the structure
net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings- The settings to apply for blocks spawning with liquids within themnet.minecraft.world.level.storage.loot.ValidationContextnow has an constructor overload taking in an emptyHolderGetter$ProviderallowsReferences- Checks whether the resolver is present
net.minecraft.client.Options#onboardingAccessibilityFinished- Disables the onboarding accessibility featurenet.minecraft.client.gui.screens.reporting.AbstractReportScreencreateHeader- Creates the report headeraddContent- Adds the report contentcreateFooter- Creates the report footeronReportChanged- Updates the report information, or sets aCannotBuildReasonif not possible to change
net.minecraft.client.multiplayer.chat.report.Report#attested- Sets whether the user has read the report and wants to send itnet.minecraft.world.level.levelgen.feature.EndPlatformFeature- A feature that generates the end platformnet.minecraft.world.level.levelgen.placement.FixedPlacement- A placement that places a feature in one of the provided positionsnet.minecraft.world.phys.AABBgetBottomCenter- Gets theVec3representing the bottom center of the boxgetMinPosition- Gets theVec3representing the smallest coordinate of the boxgetMaxPosition- Gets theVec3representing the largest coordinate of the box
net.minecraft.world.entity.player.Player#isIgnoringFallDamageFromCurrentImpulse- Returns whether the player should ignore fall damagenet.minecraft.world.item.LeadItem#leashableInArea- Returns a list of Leashable entities within a 7 block radius of the provided block position
net.minecraft.advancements.critereon.EnchantmentPredicatenow takes in aHolderSet<Enchantment- The previous constructor still exists as an overload
net.minecraft.advancements.critereon.EntityFlagsPredicatenow takes in a boolean for if the entity is on the ground or flyingnet.minecraft.advancements.critereon.EntityPredicatenow takes in a movement predicate and periodic tick which indicates when the predicate can return truenet.minecraft.advancements.critereon.LocationPredicatenow takes in a fluid predicatenet.minecraft.client.gui.components.AbstractSelectionList#setScrollAmount->setClampedScrollAmountsetScrollAmountnow delegates to this method
net.minecraft.client.gui.components.OptionsListnow longer takes in the unused integernet.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreennow takes in aLocalPlayerinstead of aPlayernet.minecraft.client.resources.language.LanguageManagernow takes in aConsumer<ClientLanguage>which acts as a callback when resources are reloadednet.minecraft.client.searchtree.PlainTextSearchTree->SearchTree#plainTextnet.minecraft.client.searchtree.RefreshableSearchTree->SearchTreenet.minecraft.commands.arguments.item.ItemInputnow takes in aDataComponentPatchinstead of aDataComponentMapnet.minecraft.core.component.TypedDataComponent#createUncheckedis now publicnet.minecraft.data.loot.BlockLootSubProvidernow takes in aHolderLookup$ProviderHAS_SILK_TOUCH->hasSilkTouchHAS_NO_SILK_TOUCH->doesNotHaveSilkTouchHAS_SHEARS_OR_SILK_TOUCH->hasShearsOrSilkTouchHAS_NO_SHEARS_OR_SILK_TOUCH->doesNotHaveShearsOrSilkTouch- Most protected static methods were turned into instance methods
net.minecraft.data.loot.EntityLootSubProvidernow takes in aHolderLookup$Providernet.minecraft.data.recipes.RecipeProvider#trapdoorBuilderis now protectednet.minecraft.recipebook.ServerPlaceRecipeaddItemToSlotnow takes in anIntegerinstead of aIterator<Integer>moveItemToGridnow takes in an integer representing the minimum count and returns the number of items remaining that can be moved with the minimum count in place
net.minecraft.resources.RegistryDataLoaderloadis now private$RegistryDatanow takes in a boolean indicating whether the data must have an element
net.minecraft.world.damagesource.CombatRules#getDamageAfterAbsorbnow takes in aLivingEntitynet.minecraft.world.entity.Entity#igniteForSecondsnow takes in a floatnet.minecraft.world.entity.LivingEntityonChangedBlocknow takes in aServerLevelgetExperienceReward->getBaseExperienceRewardgetExperienceRewardis now final and takes in theServerLevelandEntity
getRandom->Entity#getRandom(usage has not changed)dropExperiencenow takes in a nullableEntitydropCustomDeathLootno longer takes in an integerjumpFromGroundis now public for testing
net.minecraft.world.entity.monster.AbstractSkeleton#getArrownow keeps track of the weapon it was fired fromnet.minecraft.world.entity.player.Player$startAutoSpinAttacknow takes in a float representing the damage and a stack representing the item being heldnet.minecraft.world.entity.projectile.AbstractArrownow keeps track of the weapon it was fired fromsetPierceLevelis now private
net.minecraft.world.entity.projectile.ProjectileUtil#getMobArrownow keeps track of the weapon it was fired fromnet.minecraft.world.item.CrossbowItem#getChargeDurationnow takes in anItemStackandLivingEntitynet.minecraft.world.item.ItemgetAttackDamageBonusnow takes in anEntityandDamageSourceinstead of just thePlayergetUseDurationnow takes in aLivingEntity
net.minecraft.world.item.ItemStackhurtAndBreaknow takes in aServerLevelinstead of aRandomSourcehurtEnemynow returns a boolean if the entity was succesfully hurt
net.minecraft.world.item.MaceItem#canSmashAttacktakes in aLivingEntityinstead of aPlayernet.minecraft.world.item.ProjectileWeaponItem#shoottakes in aServerLevelinstead of aLevelnet.minecraft.world.item.component.CustomDataupdatenow takes in aDynamicOps<Tag>readnow has an overload that takes in aDynamicOps<Tag>
net.minecraft.world.level.Level$ExplosionInteractionnow implementsStringRepresentablenet.minecraft.world.entity.projectile.windcharge.AbstractWindCharge$WindChargeDamageCalculator->net.minecraft.world.level.SimpleExplosionDamageCalculatornet.minecraft.world.level.block.ButtonBlock#pressnow takes in a nullablePlayernet.minecraft.world.level.block.LeverBlock#pullnow takes in a nullablePlayerand does not return anythingnet.minecraft.world.level.storage.loot.LootContext$EntityTargetKILLER->ATTACKERDIRECT_KILLER->DIRECT_ATTACKERKILLER_PLAYER->ATTACKING_PLAYER
net.minecraft.world.level.storage.loot.functions.CopyNameFunction$NameSourceKILLER->ATTACKING_ENTITYKILLER_PLAYER->LAST_DAMAGE_PLAYER
net.minecraft.world.level.storage.loot.parameters.LootContextParamsKILLER_ENTITY->ATTACKING_ENTITYDIRECT_KILLER_ENTITY->DIRECT_ATTACKING_ENTITY
net.minecraft.world.level.storage.loot.predicates.LootItemConditions#TYPED_CODEC,DIRECT_CODEC,CODEChave been moved toLootItemConditionnet.minecraft.world.level.storage.loot.predicates.LootItemRandomChanceWithLootingCondition->LootItemRandomChanceWithEnchantedBonusConditionnet.minecraft.world.phys.shapes.VoxelShape#getCoordsis now publicnet.minecraft.advancements.critereon.DamageSourcePredicatenow takes in a boolean of if the damage source is directnet.minecraft.client.gui.components.SubtitleOverlay$Subtitleis now package privatenet.minecraft.network.protocol.game.ClientboundProjectilePowerPackettakes in anaccelerationPowerdouble instead of power for each of the coordinate componentsnet.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket#get*anow provides the double representing the actual acceleration vector of the coordinate instead of the shifted integernet.minecraft.world.damagesource.DamageSource#isIndirecthas been replaced withisDirect, which does the opposite checknet.minecraft.world.entity.Entity#pushnow contains an overload that takes in aVec3net.minecraft.world.entity.LivingEntity#eatis now final- A separate overload taking in the
FoodPropertiescan now be overridden
- A separate overload taking in the
net.minecraft.world.entity.ai.attributes.AttributeMap#getDirtyAttributes->getAttributestoUpdatenet.minecraft.world.entity.animal.frog.Tadpole#HITBOX_WIDTH,HITBOX_HEIGHTis now finalnet.minecraft.world.entity.npc.AbstractVillager#getOffersnow throws an error if called on the logical clientnet.minecraft.world.entity.projectile.AbstractHurtingProjectileconstructors now take inVec3to assign the directional movement of the acceleration power rather than the coordinate powersATTACK_DEFLECTION_SCALE->INITIAL_ACCELERATION_POWERBOUNCE_DEFELECTION_SCALE->DEFLECTION_SCALExPower,yPower,zPower->accelerationPower
net.minecraft.world.food.FoodData#eat(ItemStack)->eat(FoodProperties)net.minecraft.world.food.FoodPropertiesnow takes in a stack representing what the food turns into once eatennet.minecraft.world.item.CrossbowItem#getChargeDurationno longer takes in anItemStacknet.minecraft.world.item.ItemStacktransmuteCopynow has an overload which takes in the current counttransmuteCopyIgnoreEmptyis now private
net.minecraft.world.level.ChunkPos#getChessboardDistancenow has an overload to take in the x and z coordinates without being wrapped in aChunkPosnet.minecraft.world.level.block.LecternBlock#tryPlaceBooknow takes in aLivingEntityinstead of anEntitynet.minecraft.world.level.block.entity.CampfireBlockEntity#placeFoodnow takes in aLivingEntityinstead of anEntitynet.minecraft.world.level.chunk.ChunkAccess#getStatus->getPersistedStatusnet.minecraft.world.level.chunk.ChunkGenerator#createBiomes,fillFromNoiseno longer takes in anExecutornet.minecraft.world.level.levelgen.structure.pools.JigsawPlacement#addPiecesnow takes in aDimensionPaddingwhen determining the starting generation pointcom.mojang.blaze3d.systems.RenderSystemglBindBuffer(int, IntSupplier)->glBindBuffer(int, int)glBindVertexArray(Supplier<Integer>)->glBindVertexArray(int)setupOverlayColor(IntSupplier, int)->setupOverlayColor(int, int)
net.minecraft.advancements.critereon.EntityPredicate#location,steppingOnLocationhas been wrapped into a$LocationWrappersubclass- This does not affect currently generated entity predicates
net.minecraft.client.Options#menuBackgroundBlurriness,getMenuBackgroundBlurrinessnow returns an integernet.minecraft.client.renderer.GameRenderer#MAX_BLUR_RADIUSis now public and an integernet.minecraft.gametest.framework.GameTestHelper#getBlockEntitynow throws an exception if the block entity is missingnet.minecraft.network.protocol.game.ServerboundUseItemPacketnow takes in the y and x rotation of the itemnet.minecraft.server.level.ServerLevel#addDuringCommandTeleport,#addDuringPortalTeleporthave been combined intoaddDuringTeleportby checking whether the entity is aServerPlayernet.minecraft.server.level.ServerPlayer#seenCreditsis now publicnet.minecraft.server.players.PlayerList#respawnnow takes in anEntity$RemovalReasonnet.minecraft.world.effect.OozingMobEffect#numberOfSlimesToSpawn(int, int, int)->numberOfSlimesToSpawn(int, NearbySlimes, int)net.minecraft.world.entity.EntitysetOnGroundWithKnownMovement->setOnGroundWithMovementgetBlockPosBelowThatAffectsMyMovementis now public
net.minecraft.world.entity.EquipmentSlotnow takes in an integer represent the max count the slot can have, or 0 if unrestricted- Can be applied via
limitwhich splits the current item stack
- Can be applied via
net.minecraft.world.entity.LivingEntitydropAllDeathLoot,dropCustomDeathLootnow takes in aServerLevelbroadcastBreakEvent->onEquippedItemBrokengetEquipmentSlotForItemis now an instance method
net.minecraft.world.entity.ai.attributes.AttributeMap#assignValues->assignAllValuesnet.minecraft.world.entity.raid.Raider#applyRaidBuffsnow takes in aServerLevelnet.minecraft.world.item.ItemStack#hurtAndBreaknow takes in aConsumerof the brokenIteminstead of aRunnablenet.minecraft.CrashReportgetFriendlyReportandsaveToFilenow takes in aReportTypeand a list of header strings- There is also an overload that just takes in the
ReportType
- There is also an overload that just takes in the
getSaveFilenow returns aPath
net.minecraft.client.gui.screens.DisconnectedScreeencan now take in a record containing the disconnection detailsDisConnectionDetailsprovide an optional path to the report and an optional string to the bug report link
net.minecraft.client.renderer.LevelRenderer#playStreamingMusic->playJukeboxSongstopJukeboxSongAndNotifyNearbystops playing the current song
net.minecraft.client.resources.sounds.SimpleSoundInstance#forRecord->forJukeboxSongnet.minecraft.client.resources.sounds.Soundnow takes in aResourceLocationinstead of aStringnet.minecraft.network.PacketListeneronDisconnectnow takes inDisconnectionDetailsinstead of aComponentfillListenerSpecificCrashDetailsnow takes in aCrashReport
net.minecraft.server.MinecraftServergetServerDirectory,getFilenow returns aPathisNetherEnabled->isLevelEnabled
net.minecraft.world.entity.ai.behavior.AnimalPanicnow takes in aFunction<PathfinderMob, TagKey<DamageType>>instead of a simplePredicatenet.minecraft.world.entity.ai.goal.FollowOwnerGoalno longer takes in a boolean checking whether the entity can fly- These methods have been moved to
TamableAnimal
- These methods have been moved to
net.minecraft.world.entity.ai.goal.PanicGoalnow takes in aFunction<PathfinderMob, TagKey<DamageType>>instead of a simplePredicatenet.minecraft.world.entity.projectile.Projectile#deflectnow returns a boolean indicating whether the deflection was successfulnet.minecraft.world.item.CreativeModeTabe#getBackgroundSuffix->getBackgroundTexturenet.minecraft.world.item.DyeColor#getTextureDiffuseColors->getTextureDiffuseColornet.minecraft.world.level.block.entity.BeaconBlockEntity$BeaconBeamSection#getColornow returns an integernet.minecraft.world.level.storage.loot.LootDataTypeno longer takes in a directory, instead it grabs that from the location of theResourceKeynet.minecraft.client.gui.screens.Scnree#narrationEnabled->updateNarratorStatus(boolean)net.minecraft.client.gui.screens.inventory.HorseInventoryScreentakes in an integer representing the number of inventory columns to displaynet.minecraft.client.renderer.block.model.BlockElementFaceis now a recordnet.minecraft.client.resources.model.ModelBakery#getModelis now package-privatenet.minecraft.client.resources.model.ModelResourceLocationis now a recordinventorymethod for items
net.minecraft.client.resources.model.UnbakedModel#bakeQuadno longer takes in aResourceLocationnet.minecraft.core.BlockMath#getUVLockTransformno longer takes in aSupplier<String>net.minecraft.gametest.framework.GameTestBatchFactory#toGameTestBatchis now publicnet.minecraft.gametest.framework.GameTestRunnernow takes in a boolean indicating whether to halt on errornet.minecraft.network.protocol.ProtocolInfoBuilderserverboundProtocolUnbound->serverboundProtocolclientboundProtocolUnbound->clientboundProtocol
net.minecraft.network.protocol.game.ClientboundAddEntityPacketnow takes in theServerEntityfor the first two packet constructorsnet.minecraft.server.MinecraftServernow implementsChunkIOErrorReporternet.minecraft.util.ExtraCodecs#QUATERNIONF_COMPONENTSnow normalizes the quaternion on encodenet.minecraft.world.entity.Entity#getAddEntityPacketnow takes in aServerEntitynet.minecraft.world.entity.Mobleash methods have been moved toLeashablenet.minecraft.world.entity.Saddleable#equipSaddlenow takes in theItemStackbeing equippednet.minecraft.world.entity.ai.village.poi.PoiManagernow takes in aChunkIOErrorReporternet.minecraft.world.level.chunk.storage.ChunkSerializer#readnow takes in aRegionStorageInfonet.minecraft.world.level.chunk.storage.SectionStoragenow takes in aChunkIOErrorReporternet.minecraft.world.level.levelgen.structure.PoolElementStructurePiecenow takes inLiquidSettingsnet.minecraft.world.level.levelgen.structure.pools.JigsawPlacement#addPiecesnow takes inLiquidSettingsnet.minecraft.world.level.levelgen.structure.pools.SinglePoolElementnow takes in anOptional<LiquidSettings>getSettingsnow takes inLiquidSettings
net.minecraft.world.level.levelgen.structure.pools.StructurePoolElementnow takes in anLiquidSettingssinglealso has overloads that takes inLiquidSettings
net.minecraft.world.level.levelgen.structure.structures.JigsawStructurenow takes inLiquidSettingsnet.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings#shouldKeepLiquids->shouldApplyWaterloggingnet.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager#getPathToGeneratedStructure,createPathToStructure->createAndValidatePathToGeneratedStructurenet.minecraft.world.level.storage.loot.predicates.LootItemRandomChanceWithEnchantedBonusConditionnow takes in a float representing the chance to unenchant the itemnet.minecraft.world.phys.shapes.CubePointRange's constructor is now publicnet.minecraft.world.phys.shapes.VoxelShape's constructor is now protectednet.minecraft.client.gui.components.Checkboxnow takes in a max width which can be passed in through the builder viaCheckbox$Builder#maxWidthnet.minecraft.client.gui.components.MultiLineLabelcreatemethods withFormattedTexthas been removedcreatemethods withLists now take in a component varargscreateFixed->createrenderCentered,renderLeftAlignedno longer return anythingrenderBackgroundCenteredis removedTextAndWidthis now a record
net.minecraft.commands.arguments.selector.EntitySelector#predicate->contextFreePredicate- Takes in a
List<Predicate<Entity>>now
- Takes in a
net.minecraft.world.level.border.WorldBorderisWithinBoundsnow has overloads forVec3and four doubles representing two xz coordinatesclampToBoundsnow has overloads forBlockPosandVec3clampToBounds(AABB)is removed
net.minecraft.server.level.ServerPlayer#onInsideBlockis now public, only for this overload
net.minecraft.client.MinecraftgetSearchTree,populateSearchTreerenderOnThread
net.minecraft.client.searchtree.SearchRegistrynet.minecraft.entity.LivingEntity#canSpawnSoulSpeedParticle,spawnSoulSpeedParticlenet.minecraft.world.entity.projectile.AbstractArrowsetKnockback,getKnockbacksetShotFromCrossbow
net.minecraft.world.item.ProjectileWeaponItem#hasInfiniteArrowscom.mojang.blaze3d.systems.RenderSysteminitGameThread,isOnGameThreadassertInInitPhase,isInInitPhaseassertOnGameThreadOrInit,assertOnGameThread
net.minecraft.client.gui.screens.Screen#advancePanoramaTimenet.minecraft.world.entity.EquipmentSlot#byTypeAndIndexnet.minecraft.world.entity.Mob#canWearBodyArmor- Use
canUseSlot(EquipmentSlot.BODY)instead
- Use
com.mojang.blaze3d.platform.MemoryTrackernet.minecraft.server.level.ServerLevel#makeObsidianPlatformnet.minecraft.world.entity.Entity#getPassengerClosestTonet.minecraft.client.resources.model.ModelBakery$ModelGroupKeynet.minecraft.data.worldgen.Structures#structure
@ChampionAsh5357 Are there any changes related to data generation?
Take example of this code:
It should add 4 new enchantments under existing Vanilla ARMOR_EXCLUSIVE tag.
The provider is registered normally in data generator:
dataGen.addProvider(event.includeServer(), new ModEnchantmentTagsProvider(packOutput, lookupProvider));However, it cannot generate enchantment tag as it throws this error while running data generation:
Couldn't define tag minecraft:exclusive_set/armor as it is missing following references: uniquemagic:freezing_protection,uniquemagic:lightning_protection,uniquemagic:magic_protection,uniquemagic:sonic_protectionAlthough enchantments are working correctly, we have not been able to tag them with existing enchantment tag.
Are there any additional steps that must be taken to have this work properly?