Minecraft 1.21.2/3 -> 1.21.4 Mod Migration Primer
This is a high level, non-exhaustive overview on how to migrate your mod from 1.21.2/3 to 1.21.4. This does not look at any specific mod loader, just the changes to the vanilla classes. All provided names use the official mojang mappings.
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 file an issue on this repository or ping @ChampionAsh5357 in the Neoforged Discord server.
Pack Changes
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.
Client Items
Minecraft has moved the lookup and definition of how an item should be rendered to its own data generated system, which will be referred to as Client Items, located at assets/<namespace>/items/<path>.json. Client Items is similar to the block state model definition, but has the potential to have more information enscribed in the future. Currently, it functions as simply a linker to the models used for rendering.
All client items contain some ItemModel$Unbaked using the model field. Each unbaked model has an associated type, which defines how the item should be set up for rendering, or rendered in one specific case. These types can be found within ItemModels. This primer will review all but one type, as that unbaked model type is specifically for bundles when selecting an item.
The item also contains a properties field which holds some metadata-related parameters. Currently, it only specifies a boolean that, when false, make the hand swap the currently held item instantly rather than animate the hand coming up.
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "" // Set type here
// Add additional parameters
},
"properties": {
// When false, disables animation when swapping this item into the hand
"hand_animation_on_swap": false
}
}
A Basic Model
The basic model definition is handled by the minecraft:model type. This contains two fields: model, to define the relative location of the model JSON, and an optional list of tints, to define how to tint each index.
model points to the model JSON, relative to assets/<namespace>/models/<path>.json. In most instances, a client item defintion will look something like this:
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:model",
// Points to 'assets/examplemod/models/item/example_item.json'
"model": "examplemod:item/example_item"
}
}
Tint Sources
In model JSONs, some element faces will have a tintindex field which references some index into the tints list in the minecraft:model unbaked model type. The list of tints are ItemTintSources, which are all defined in net.minecraft.client.color.item.*. All defined tint sources can be found within ItemTintSources, like minecraft:constant for a constant color, or minecraft:dye, to use the color of the DataComponents#DYED_COLOR or default if not present. All tint sources must return an opaque color, though all sources typically apply this by calling ARGB#opaque.
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:model",
// Points to 'assets/examplemod/models/item/example_item.json'
"model": "examplemod:item/example_item",
// A list of tints to apply
"tints": [
{
// For when tintindex: 0
"type": "minecraft:constant",
// 0x00FF00 (or pure green)
"value": 65280
},
{
// For when tintindex: 1
"type": "minecraft:dye",
// 0x0000FF (or pure blue)
// Only is called if `DataComponents#DYED_COLOR` is not set
"default": 255
}
]
}
}
To create your own ItemTintSource, you need to implement the calculate method register the MapCodec associated for the type field. calculate takes in the current ItemStack, level, and holding entity and returns an RGB integer with an opaque alpha, defining how the layer should be tinted.
Then, the MapCodec needs to be registered to ItemTintSources#ID_MAPPER, though this field is private by default, so some access changes or reflection needs to be applied.
// The item source class
public record FromDamage(int defaultColor) implements ItemTintSource {
public static final MapCodec<FromDamage> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
ExtraCodecs.RGB_COLOR_CODEC.fieldOf("default").forGetter(FromDamage::defaultColor)
).apply(instance, FromDamage::new)
);
public FromDamage(int defaultColor) {
this.defaultColor = ARGB.opaque(defaultColor);
}
@Override
public int calculate(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity) {
return stack.isDamaged() ? ARGB.opaque(stack.getBarColor()) : defaultColor;
}
@Override
public MapCodec<FromDamage> type() {
return MAP_CODEC;
}
}
// Then, in some initialization location where ItemTintSources#ID_MAPPER is exposed
ItemTintSources.ID_MAPPER.put(
// The registry name
ResourceLocation.fromNamespaceAndPath("examplemod", "from_damage"),
// The map codec
FromDamage.MAP_CODEC
);
// For some object in the 'tints' array
{
"type": "examplemod:from_damage",
// 0x0000FF (or pure blue)
// Only is called if the item has not been damaged yet
"default": 255
}
Ranged Property Model
Ranged property models, as defined by the minecraft:range_dispatch unbaked model type, are the most similar to the previous item override system. Essentially, the type defines some item property that can be scaled along with a list of thresholds and associated models. The model chosen is the one with the closest threshold value that is not over the property (e.g. if the property value is 4 and we have thresholds 3 and 5, 3 would be chosen as it is the cloest without going over). The item property is defined via a RangeSelectItemModelProperty, which takes in the stack, level, entity, and some seeded value to get a float, usually scaled betwen 0 and 1 depending on the implementation. All properties can be found within net.minecraft.client.renderer.item.properties.numeric.* and are registered in RangeSelectItemModelProperties, such as minecraft:cooldown, for the cooldown percentage, or minecraft:count, for the current number of items in the stack or percentage of the max stack size when normalized.
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:range_dispatch",
// The `RangeSelectItemModelProperty` to use
"property": "minecraft:count",
// A scalar to multiply to the computed property value
// If count was 0.3 and scale was 0.2, then the threshold checked would be 0.3*0.2=0.06
"scale": 1,
"fallback": {
// The fallback model to use if no threshold matches
// Can be any unbaked model type
"type": "minecraft:model",
"model": "examplemod:item/example_item"
},
// ~~ Properties defined by `Count` ~~
// When true, normalizes the count using its max stack size
"normalize": true,
// ~~ Entries with threshold information ~~
"entries": [
{
// When the count is a third of its current max stack size
"threshold": 0.33,
"model": {
// Can be any unbaked model type
}
},
{
// When the count is two thirds of its current max stack size
"threshold": 0.66,
"model": {
// Can be any unbaked model type
}
}
]
}
}
To create your own RangeSelectItemModelProperty, you need to implement the get method register the MapCodec associated for the type field. get takes in the stack, level, entity, and seeded value and returns an arbitrary float to be interpreted by the ranged dispatch model.
Then, the MapCodec needs to be registered to RangeSelectItemModelProperties#ID_MAPPER, though this field is private by default, so some access changes or reflection needs to be applied.
// The ranged property class
public record AppliedEnchantments() implements RangeSelectItemModelProperty {
public static final MapCodec<AppliedEnchantments> MAP_CODEC = MapCodec.unit(new AppliedEnchantments());
@Override
public float get(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) {
return (float) stack.getEnchantments().size();
}
@Override
public MapCodec<AppliedEnchantments> type() {
return MAP_CODEC;
}
}
// Then, in some initialization location where RangeSelectItemModelProperties#ID_MAPPER is exposed
RangeSelectItemModelProperties.ID_MAPPER.put(
// The registry name
ResourceLocation.fromNamespaceAndPath("examplemod", "applied_enchantments"),
// The map codec
AppliedEnchantments.MAP_CODEC
);
// For some client item in 'model'
{
"type": "minecraft:range_dispatch",
// The `RangeSelectItemModelProperty` to use
"property": "examplemod:applied_enchantments",
// A scalar to multiply to the computed property value
"scale": 0.5,
"fallback": {
// The fallback model to use if no threshold matches
// Can be any unbaked model type
"type": "minecraft:model",
"model": "examplemod:item/example_item"
},
// ~~ Properties defined by `AppliedEnchantments` ~~
// N/A (no arguments to constructor)
// ~~ Entries with threshold information ~~
"entries": [
{
// When there is one enchantment present
// Since 1 * the scale 0.5 = 0.5
"threshold": 0.5,
"model": {
// Can be any unbaked model type
}
},
{
// When there are two enchantments present
"threshold": 1,
"model": {
// Can be any unbaked model type
}
}
]
}
Select Property Model
Select property models, as defined by the minecraft:select unbaked model type, are functionally similar to ranged property models, except now it switches on some property, typically an enum. The item property is defined via a SelectItemModelProperty, which takes in the stack, level, entity, some seeded value, and the current display context to get one of the property values. All properties can be found within net.minecraft.client.renderer.item.properties.select.* and are registered in SelectItemModelProperties, such as minecraft:block_state, for the stringified value of a specified block state property, or minecraft:display_context, for the current ItemDisplayContext.
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:select",
// The `SelectItemModelProperty` to use
"property": "minecraft:display_context",
"fallback": {
// The fallback model to use if no threshold matches
// Can be any unbaked model type
"type": "minecraft:model",
"model": "examplemod:item/example_item"
},
// ~~ Properties defined by `DisplayContext` ~~
// N/A (no arguments to constructor)
// ~~ Switch cases based on Selectable Property ~~
"cases": [
{
// When the display context is `ItemDisplayContext#GUI`
"when": "gui",
"model": {
// Can be any unbaked model type
}
},
{
// When the display context is `ItemDisplayContext#FIRST_PERSON_RIGHT_HAND`
"when": "firstperson_righthand",
"model": {
// Can be any unbaked model type
}
}
]
}
}
To create your own SelectItemModelProperty, you need to implement the get method register the SelectItemModelProperty$Type associated for the type field. get takes in the stack, level, entity, seeded value, and display context and returns an encodable object to be interpreted by the select model.
Then, the MapCodec needs to be registered to SelectItemModelProperties#ID_MAPPER, though this field is private by default, so some access changes or reflection needs to be applied.
// The select property class
public record StackRarity() implements SelectItemModelProperty<Rarity> {
public static final SelectItemModelProperty.Type<StackRarity, Rarity> TYPE = SelectItemModelProperty.Type.create(
// The map codec for this property
MapCodec.unit(new StackRarity()),
// The codec for the object being selected
Rarity.CODEC
);
@Nullable
@Override
public Rarity get(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed, ItemDisplayContext displayContext) {
// When null, uses the fallback model
return stack.get(DataComponents.RARITY);
}
@Override
public SelectItemModelProperty.Type<StackRarity, Rarity> type() {
return TYPE;
}
}
// Then, in some initialization location where SelectItemModelProperties#ID_MAPPER is exposed
SelectItemModelProperties.ID_MAPPER.put(
// The registry name
ResourceLocation.fromNamespaceAndPath("examplemod", "rarity"),
// The property type
StackRarity.TYPE
);
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:select",
// The `SelectItemModelProperty` to use
"property": "examplemod:rarity",
"fallback": {
// The fallback model to use if no threshold matches
// Can be any unbaked model type
"type": "minecraft:model",
"model": "examplemod:item/example_item"
},
// ~~ Properties defined by `StackRarity` ~~
// N/A (no arguments to constructor)
// ~~ Switch cases based on Selectable Property ~~
"cases": [
{
// When rarity is `Rarity#UNCOMMON`
"when": "uncommon",
"model": {
// Can be any unbaked model type
}
},
{
// When rarity is `Rarity#RARE`
"when": "rare",
"model": {
// Can be any unbaked model type
}
}
]
}
}
Conditional Property Model
Conditional property models, as defined by the minecraft:condition unbaked model type, are functionally similar to ranged property models, except now it switches on boolean. These are usually combined with range dispatch, such as when pulling the bow. The item property is defined via a ConditionalItemModelProperty, which takes in the stack, level, entity, some seeded value, and the current display context to get a true of false statement. All properties can be found within net.minecraft.client.renderer.item.properties.conditional.* and are registered in ConditionalItemModelProperties, such as minecraft:damaged, for if the item is damaged, or minecraft:has_component, if it has a given data component.
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:condition",
// The `SelectItemModelProperty` to use
"property": "minecraft:damaged",
// ~~ Properties defined by `Damaged` ~~
// N/A (no arguments to constructor)
// ~~ What the boolean outcome is ~~
"on_true": {
// Can be any unbaked model type
},
"on_false": {
// Can be any unbaked model type
}
}
}
To create your own ConditionalItemModelProperty, you need to implement the get method register the MapCodec associated for the type field. get takes in the stack, level, entity, seeded value, and display context and returns a boolean to be interpreted by on_true and on_false, respectively.
Then, the MapCodec needs to be registered to ConditionalItemModelProperties#ID_MAPPER, though this field is private by default, so some access changes or reflection needs to be applied.
// The predicate property class
public record TimePeriod(int month, MinMaxBounds.Ints dates, boolean enabled) implements ConditionalItemModelProperty {
public static final MapCodec<TimePeriod> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
Codec.intRange(1, 12).fieldOf("month").forGetter(TimePeriod::month),
MinMaxBounds.Ints.CODEC.fieldOf("dates").forGetter(TimePeriod::dates)
).apply(instance, TimePeriod::new)
);
public TimePeriod(int month, MinMaxBounds.Ints dates) {
this.month = month;
this.dates = dates;
Calendar cal = Calendar.getInstance();
this.enabled = cal.get(Calendar.MONTH) + 1 == this.month
&& this.dates.matches(cal.get(Calendar.DATE));
}
@Override
public boolean get(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed, ItemDisplayContext context) {
return this.enabled;
}
@Override
public MapCodec<TimePeriod> type() {
return MAP_CODEC;
}
}
// Then, in some initialization location where ConditionalItemModelProperties#ID_MAPPER is exposed
ConditionalItemModelProperties.ID_MAPPER.put(
// The registry name
ResourceLocation.fromNamespaceAndPath("examplemod", "time_period"),
// The map codec
TimePeriod.MAP_CODEC
);
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:condition",
// The `SelectItemModelProperty` to use
"property": "examplemod:time_period",
// ~~ Properties defined by `TimePeriod` ~~
// Month of July
"month": 7,
"dates": {
// Between July 1st - 14th
"min": 1,
"max": 14
},
// ~~ What the boolean outcome is ~~
"on_true": {
// Can be any unbaked model type
},
"on_false": {
// Can be any unbaked model type
}
}
}
Composite Model
Composite models, defined by minecraft:composite, are essentially a combination of other model types to render. Specifically, this sets up multiple players to overlay models on top of one another when rendering.
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:composite",
// Will render in the order they appear in the list
"models": [
{
// Can be any unbaked model type
},
{
// Can be any unbaked model type
}
]
}
}
Special Dynamic Models
Special dynamic models, as defined by the minecraft:special unbaked model type, are the new system for block entity without level renderers (e.g., chests, banners, and the like). Instead of storing a baked model, these provide a render method to call. The special model wrapper takes in a base model used for grabbing the basic model settings (not the elements) and a SpecialModelRenderer. All special model renderers can be found within net.minecraft.client.renderer.special.* and are registered in SpecialModelRenderers.
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:special",
// The model to read the particle texture and display transformation from
"base": "minecraft:item/template_skull",
"model": {
// The special model renderer to use
"type": "minecraft:head",
// ~~ Properties defined by `SkullSpecialRenderer.Unbaked` ~~
// The type of the skull block
"kind": "wither_skeleton"
}
}
}
To create your own SpecialModelRenderer, you need to implement both the renderer and the $Unbaked model to read the data from the JSON. The $Unbaked model creates the SpecialModelRenderer via bake and is registered using a MapCodec for its type. The SpecialModelRenderer then extracts the necessary data from the stack needed to render via extractArgument and passes that to the render method. If you do not need any information from the stack, you can implement NoDataSpecialModelRenderer instead.
Then, the MapCodec needs to be registered to SpecialModelRenderers#ID_MAPPER, though this field is private by default, so some access changes or reflection needs to be applied.
If your item is a held block, it also needs to be added to the SpecialModelRenderers#STATIC_BLOCK_MAPPING for specific rendering scenarios via BlockRenderDispatcher#renderSingleBLock (e.g. in minecart, or picked up by endermen). Both the default model renderer and the special model renderer are called in this method; allowing for both the static block model and the dynamic special model to be rendered at the same time. As this map is immutable, you will either need to replace it or hook into SpecialBlockModelRenderer and somehow add to the stored map there.
// The special renderer
public record SignSpecialRenderer(WoodType defaultType, Model model) implements SpecialModelRenderer<WoodType> {
// Render the model
@Override
public void render(@Nullable WoodType type, ItemDisplayContext displayContext, PoseStack pose, MultiBufferSource bufferSource, int light, int overlay, boolean hasFoil) {
VertexConsumer consumer = Sheets.getSignMaterial(type).buffer(bufferSource, this.model::renderType);
this.model.renderToBuffer(pose, consumer, light, overlay);
}
// Get the wood type from the stack
@Nullable
@Override
public WoodType extractArgument(ItemStack stack) {
return (stack.getItem() instanceof BlockItem item && item.getBlock() instanceof SignBlock sign)
? sign.type() : this.defaultType;
}
// The model to read the json from
public static record Unbaked(WoodType defaultType) implements SpecialModelRenderer.Unbaked {
public static final MapCodec<SignSpecialRenderer.Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
WoodType.CODEC.fieldOf("default").forGetter(SignSpecialRenderer.Unbaked::defaultType)
).apply(instance, SignSpecialRenderer.Unbaked::new)
);
// Create the special model renderer, or null if it fails
@Nullable
@Override
public SpecialModelRenderer<?> bake(EntityModelSet modelSet) {
return new SignSpecialRenderer(
this.defaultType,
SignRenderer.createSignModel(modelSet, defaultType, true)
)
}
@Overrides
public MapCodec<SignSpecialRenderer.Unbaked> type() {
return MAP_CODEC;
}
}
}
// Then, in some initialization location where SpecialModelRenderers#ID_MAPPER is exposed
SpecialModelRenderers.ID_MAPPER.put(
// The registry name
ResourceLocation.fromNamespaceAndPath("examplemod", "sign"),
// The map codec
SignSpecialRenderer.Unbaked.MAP_CODEC
);
// Let assume we can add directly to SpecialModelRenderers#STATIC_BLOCK_MAPPING as well
// We'll have a Block EXAMPLE_SIGN
SpecialModelRenderers.STATIC_BLOCK_MAPPING.put(
// The block with a special rendering as an item
EXAMPLE_SIGN,
// The unbaked renderer to use
new SignSpecialRenderer.Unbaked(WoodType.BAMBOO)
);
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "minecraft:special",
// The model to read the particle texture and display transformation from
"base": "minecraft:item/bamboo_sign",
"model": {
// The special model renderer to use
"type": "examplemod:sign",
// ~~ Properties defined by `SignSpecialRenderer.Unbaked` ~~
// The default wood type if none can be found
"default": "bamboo"
}
}
}
Rendering an Item
Rendering an item is now done through the ItemModelResolver and ItemStackRenderState. This is similar to how the EntityRenderState works: first, the ItemModelResolver sets up the ItemStackRenderState, then the state is rendered via ItemStackRenderState#render.
Let's start with the ItemStackRenderState. For rendering, the only one we care about the following methods: isEmpty, isGui3d, usesBlockLight, transform, and render. isEmpty is used to determine whether the stack should render at all. Then isGui3d, usesBlockLight, and transform are used in their associated contexts to properly position the stack to render. Finally, render takes in the pose stack, buffer source, packed light, and overlay texture to render the item in its appropriate location.
ItemModelResolver is responsible for setting the information on the ItemStackRenderState needed to render. This is done through updateForLiving for items held by living entities, updateForNonLiving for items held by other kinds of entities, and updateforTopItem, for all other scenarios. updateForItem, which the previous two methods delegate to, take in the render state, the stack, the display context, if the stack is in the left hand, the level, the entity, and some seeded value. This will effectively clear the previous state via ItemStackRenderState#clear and then set up the new state via a delegate to ItemModel#update. The ItemModelResolver can always be obtained via Minecraft#getItemModelResolver, if you are not within a renderer context (e.g., block entity, entity).
// In its most simple form, assuming you are not doing any transformations (which you should as necessary)
public class ExampleRenderer {
private final ItemStackRenderState state = new ItemStackRenderState();
public void render(ItemStack stack, Level level, PoseStack pose, MultiBufferSource bufferSource) {
// First update the render state
Minecraft.getInstance().getItemModelResolver().updateForTopItem(
// The render state
this.state,
// The stack to update the state with
stack,
// The display context to render within
ItemDisplayContext.NONE,
// Whether it is in the left hand of the entity (use false when unknown)
false,
// The current level (can be null)
level,
// The holding entity (can be null)
null,
// An arbitrary seed value
0
);
// Perform any desired transformations here
// Then render the state
this.state.render(
// The pose stack with the required transformations
pose,
// The buffer sources
bufferSource,
// The packed light value
LightTexture.FULL_BRIGHT,
// The overlay texture value
OverlayTexture.NO_OVERLAY
);
}
}
Custom Item Model Defintions
To make a custom item model definition, we need to look at a few more methods in ItemStackRenderState which, although you won't typically use, is useful to understand: ensureCapacity and newLayer. Both of these are responsible for ensuring there are enough ItemStackRenderState$LayerRenderStates if you happen to be overlaying multiple models at once. Effectively, every time you are planning to render something in an unbaked model, newLayer should be called. If you plan on rendering multiple things on top of one another, then ensureCapacity should be set with the number of layers that you plan to render before calling newLayer.
An item model definition is made up of the ItemModel, which functionally defines a 'baked model' and its ItemModel$Unbaked, used for serialization.
The unbaked variant has two methods: bake, which is used to create the ItemModel, and type, which references the MapCodec to be registered to ItemModels#ID_MAPPER, though this field is private by default, so some access changes or reflection needs to be applied. bake takes in the $BakingContext, which contains the ModelBaker to get BakedModels, the EntityModelSet for entity models, and the missing ItemModel.
The baked variant only has one method update, which is responsible for setting up everything necessary on the ItemStackRenderState. The model does no rendering itself.
public record RenderTypeModelWrapper(BakedModel model, RenderType type) implements ItemModel {
// Update the render state
@Override
public void update(ItemStackRenderState state, ItemStack stack, ItemModelResolver resolver, ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) {
ItemStackRenderState.LayerRenderState layerState = state.newLayer();
if (stack.hasFoil()) {
layerState.setFoilType(ItemStackRenderState.FoilType.STANDARD);
}
layerState.setupBlockModel(this.model, this.type);
}
public static record Unbaked(ResourceLocation model, RenderType type) implements ItemModel.Unbaked {
// Create a render type map for the codec
private static final BiMap<String, RenderType> RENDER_TYPES = Util.make(HashBiMap.create(), map -> {
map.put("translucent_item", Sheets.translucentItemSheet());
map.put("cutout_block", Sheets.cutoutBlockSheet());
});
private static final Codec<RenderType> RENDER_TYPE_CODEC = ExtraCodecs.idResolverCodec(Codec.STRING, RENDER_TYPES::get, RENDER_TYPES.inverse()::get);
// The map codec to register
public static final MapCodec<RenderTypeModelWrapper.Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("model").forGetter(RenderTypeModelWrapper.Unbaked::model),
RENDER_TYPE_CODEC.fieldOf("render_type").forGetter(RenderTypeModelWrapper.Unbaked::type)
)
.apply(instance, RenderTypeModelWrapper.Unbaked::new)
);
@Override
public void resolveDependencies(ResolvableModel.Resolver resolver) {
// Resolve model dependencies, so pass in all known resource locations
resolver.resolve(this.model);
}
@Override
public ItemModel bake(ItemModel.BakingContext context) {
// Get the baked model and return
BakedModel baked = context.bake(this.model);
return new RenderTypeModelWrapper(baked, this.type);
}
@Override
public MapCodec<RenderTypeModelWrapper.Unbaked> type() {
return MAP_CODEC;
}
}
}
// Then, in some initialization location where ItemModels#ID_MAPPER is exposed
ItemModels.ID_MAPPER.put(
// The registry name
ResourceLocation.fromNamespaceAndPath("examplemod", "render_type"),
// The map codec
RenderTypeModelWrapper.Unbaked.MAP_CODEC
);
// For some item 'examplemod:example_item'
// JSON at 'assets/examplemod/items/example_item.json'
{
"model": {
"type": "examplemod:render_type",
// Points to 'assets/examplemod/models/item/example_item.json'
"model": "examplemod:item/example_item",
// Set the render type to use when rendering
"render_type": "cutout_block"
}
}
net.minecraft.clientClientBootstrap- Registers the maps backing the client; currently used for item model definitions.MinecraftgetEquipmentModelsis removed, only directly accessible in theEntityRendererProvider$Context#getEquipmentAssetsgetItemModelResolver- Returns the updater for resolving the current model to be rendered in theItemStackRenderState$LayerRenderState.
KeyMapping#get- Gets a key mapping based on its translation key.
net.minecraft.client.color.itemConstant- A constant to tint the item texture.CustomModelDataSource- Gets the color to tint based on an index in theDataComponent#CUSTOM_MODEL_DATAdata component. If no index is found or is out of bounds, then the default color is used.Dye- Gets the color to tint using theDataComponent#DYED_COLORdata component.Firework- Gets the color to tint using theDataComponent#FIRE_EXPLOSIONdata component.GrassColorSource- Gets the color to tint based on the provided temperature and downfall values.ItemColor->ItemTintSource, not one-to-one as indexing is setup by providing multipleItemTintSources in the model list.ItemColorsclass is removed, now data generated asItemTintSourcesItemTintSources- A registry of sources for tinting an item texture in a model.MapColor- Gets the color to tint using theDataComponent#MAP_COLORdata component.Potion- Gets the color to tint using theDataComponent#POTION_CONTENTSdata component.TeamColor- Gets the color based on the holding entity's team color.
net.minecraft.client.data.Main- The entrypoint for client data generation.net.minecraft.client.particle.BreakingItemParticlenow takes in anItemStackRenderStateinstead of anItemStack$ItemParticleProvider- An abstract particle provide that provides a simple method to calculate theItemStackRenderState.
net.minecraft.client.rendererBlockEntityWithoutLevelRendererclass is removed, replaced by theNoDataSpecialModelRendererdatagen systemItemInHandRenderernow takes in anItemModelResolverItemModelShaperis removed, as the methods are available within theModelManagerSheetsgetBedMaterial- Gets the bed material from the dye color.colorToResourceMaterial- Gets the resource location of the dye color.createBedMaterial- Creates the bed material from the dye color or resource location.getShulkerBoxMaterial- Gets the shulker box material from the dye color.colorToShulkerMaterial- Gets the resource location of the dye color for the shulker box.createShulkerMaterial- Creates the shulker box material from the dye color or resource location.chestMaterial- Creates a new material for a chest with the given resource location.
SpecialBlockModelRenderer- A map of blocks to special renderers for item variants.
net.minecraft.client.renderer.block.BlockRenderDispatchernow takes in a suppliedSpecialBlockModelRendererinstead of aBlockEntityWithoutLevelRenderernet.minecraft.client.renderer.block.modelBakedOverridesclass is removed, replaced by theRangeSelectItemModelPropertydatagen systemBlockModelnow takes in aTextureSlots$Datainstead of just a material map, and no longer takes in a list ofItemOverridesMISSING_MATERIALis removed, replaced byminecraft:missingnotextureMap->textureSlots, now private, not one-to-oneparentis now private, not one-to-oneparentLocationis now privatehasAmbientOcclusion->getAmbientOcclusionisResolvedis removedgetOverridesis removedgetParent- Returns the unbaked parent model.getTextureSlots- Returns the texture data for the model.getElementsis now package-private$GuiLight->UnbakedModel$GuiLight
FaceBakerybakeQuadis now staticcalculateFacingis now private
ItemModelGeneratornow implementsUnbakedModelItemOverrideclass is removed, replaced by theRangeSelectItemModelPropertydatagen systemItemTransformsis now a recordhasTransformis removed
TextureSlots- A class which handles the texture mapping within a model. The data is read from$Dataand stored as$SlotContentsuntil it is resolved during the baking process intoMaterials.UnbakedBlockStateModelnow extendsResolvableModelinstead ofUnbakedModelbake- Bakes the block state into its selectable models.
Variantis now a record
net.minecraft.client.renderer.blockentityBannerRenderernow has an overload constructor which takes in theEntityModelSetrenderInHand- Renders the item model of the banner.
BedRenderernow has an overload constructor which takes in theEntityModelSetrenderInHand- Renders the item model of the bed.
BlockEntityRenderDispatcher(Font, EntityModelSet, Supplier<BlockRenderDispatcher>, Supplier<ItemRenderer>, Supplier<EntityRenderDispatcher>)->BlockEntityRenderDispatcher(Font, Supplier<EntityModelSet>, BlockRenderDispatcher, ItemModelResolver, ItemRenderer, EntityRenderDispatcher)renderItemis removed, implemented in their specific classes
BlockEntityRendererProvidernow takes in anItemModelResolvergetItemModelResolver- Gets the resolver which returns the item models.
ChestRenderer#xmasTextures- Returns whether christmas textures should render on a chest.DecoratedPotRenderernow has an overload constructor which takes in theEntityModelSetrenderInHand- Renders the item model of the pot.
ShulkerBoxRenderernow has an overload constructor which takes in theEntityModelSetrender- Renders the shulker box.$ShulkerBoxModel#animateno longer takes in theShulkerBoxBlockEntity
SkullblockRenderer#createSkullRenderers->createModel, not one-to-one
net.minecraft.client.renderer.entityEntityRenderDispatchernow takes in anIteModelResolver, a suppliedEntityModelSetinstead of the instance, and anEquipmentAssetManagerinstead of aEquipmentModelSetEntityRendererProvider$Contextnow takes in anItemModelResolverinstead of anItemRenderer, and anEquipmentAssetManagerinstead of aEquipmentModelSetgetItemRenderer->getItemModelResolver, not one-to-onegetEquipmentModels->getEquipmentAssets
FishingHookRenderer- Returns the holding arm of the fishing hook.HumanoidMobRenderergetArmPose- Returns the arm pose of the entity.extractHumanoidRenderStatenow takes in anItemModelResolver
ItemEntityRenderergetSeedForItemStackis removedrenderMultipleFromCountnow takes in theItemClusterRenderState, and removes theItemRenderer,ItemStack,BakedModel, and 3d boolean
ItemRendererno longer implementsResourceManagerReloadListener- The constructor now only takes in the
ItemModelResolver render->renderItem, not one-to-onerenderBundleItemis removedgetModel,resolveItemModelis removed
- The constructor now only takes in the
LivingEntityRenderer#itemRenderer->itemModelResolver, not one-to-oneOminousItemSpawnerRenderernow uses theItemClusterRenderStateSkeletonRenderer#getArmPose->AbstractSkeletonRenderer#getArmPoseSnowGolemRenderernow uses theSnowGolemRenderState
net.minecraft.client.renderer.entity.layersCrossArmsItemLayernow uses theHoldingEntityRenderStateCustomHeadLayerno longer takes in theItemRendererDolphinCarryingItemLayerno longer takes in theItemRendererEquipmentLayerRenderer$TrimSpriteKeynow takes in aResourceKey<EquipmentAsset>textureId- Gets the texture id for the trim.
FoxHeldItemLayerno longer takes in theItemRendererItemInHandLayernow uses theArmedEntityRenderState- The constructor no longer takes in the
ItemRenderer renderArmWithItemno longer takes in theBakedModel,ItemStack, orItemDisplayContextand instead theItemStackRenderState
- The constructor no longer takes in the
LivingEntityEmissiveLayernow takes in a boolean which determines whether the layer is always visiblePandaHoldsItemLayerno longer takes in theItemRendererPlayerItemInHandLayerno longer takes in theItemRendererrenderArmWithItemno longer takes in theBakedModel,ItemStack, orItemDisplayContextand instead theItemStackRenderState
SnowGolemHeadLayernow uses theSnowGolemRenderStateWitchItemLayerno longer takes in theItemRenderer
net.minecraft.client.renderer.entity.player.PlayerRenderer#getArmPoseis now privatenet.minecraft.client.renderer.entity.stateArmedEntityRenderState- A render state for an entity that holds items in their right and left hands.HoldingEntityRenderState- A render state for an entity that holds a single item.ItemClusterRenderState- A render state for an item that should be rendered multiple times.ItemDisplayEntityRenderState#itemRenderState,itemModel->item, not one-to-oneItemEntityRenderState#itemModel,item->ItemClusterRenderState#item, not one-to-oneItemFrameRenderState#itemStack,itemModel->item, not one-to-oneLivingEntityRenderStateheadItemModel,headItem->headItem, not one-to-one- Arm and Hand methods moved to
ArmedEntityRenderState
OminousItemSpawnerRenderState->ItemClusterRenderStatePlayerRenderStatemainHandState,offHandState->ArmedEntityRenderStatemethodsheldOnHead- Represents the item stack on the head of the player.
SkeletonRenderState#isHoldingBow- Represents if the skeleton is holding a bow.SnowGolemRenderState- The render state for the snow golem.ThrownItemRenderState#item,itemModel->item, not one-to-oneWitchRenderState#isHoldingPotion- Whether the witch is holding a potion or not.
net.minecraft.client.renderer.itemBlockModelWrapper- The basic model definition that contains the model and its associated tints.BundleSelectedItemSpecialRenderer- A special renderer for a stack selected by a bundle.ClampedItemPropertyFunction,ItemPropertyFunction->.properties.numeric.*classes depending on the situation and propertyClientItem- The base item that represents the model definition inassets/<modid>/items.CompositeModel- Overlays multiple models together.ConditionalItemModel- A model that shows a different model based on a boolean.EmptyModel- A model that renders nothing.ItemModel- The base item model that updates the stack render state as necessary.ItemModelResolver- The resolver that updates the stack render state.ItemModels- Contains all potential item models for aClientItem.ItemPropertiesclass is removedItemStackRenderState- The render state representing the stack to render.MissingItemModel- A model that represents the missing model.RangeSelectItemModel- A model that contains some range of values that applies the associated model that meets the threshold.SelectItemModel- An item model that switches based on the provided property.SpecialModelWrapper- An item model for models that are rendered dynamically, such as chests.
net.minecraft.client.renderer.item.properties.conditionalBroken- If the item only has one durability left.BundleHasSelectedItem- If the bundle is holding the selected item.ConditionalItemModelProperties- Contains all potential conditional property types.ConditionalItemModelProperty- Represents a property that returns some boolean.CustomModelDataProperty- If the current index is set to true withinDataComponents#CUSTOM_MODEL_DATA.Damaged- If the item is damaged.ExtendedView- If the display context is a gui and the shift key is down.FishingRodCast- If the fishing rod is being used.HasComponent- Whether it has the associated data component.IsCarried- If the item is being carried in the current menu.IsKeybindDown- If the key mapping is being pressed.IsSelected- If the item is selected in the hotbar.IsUsingItem- If the item is being used.IsViewEntity- Whether the holding entity is the current camera entity.
net.minecraft.client.renderer.item.properties.numericBundleFullness- A threshold based on the bundle contents.CompassAngle- A threshold on the currrent angle state.CompassAngleState- A threshold based on the current compass angle towards its target.Cooldown- A threshold based on the current cooldown percentage.Count- A threshold based on the stack count.CrossbowPull- A threshold based on the crossbow being pulled.CustomModelDataProperty- If the current index has set theshold value withinDataComponents#CUSTOM_MODEL_DATA.Damage- A threshold based on the durability percentage remaining.NeedleDirectionHelper- An abstract class which help point the position needle in the correct direction.RangeSelectItemModelProperties- Contains all potential ranged property types.RangeSelectItemModelProperty- Represents a property that returns some threshold of a float.Time- A threshold based on the current time of day.UseCycle- A threshold based on the remaining time left normalized to some period modulo in the stack being used.UseDuration- A threshold based on the remaining time left in the stack being used.
net.minecraft.client.renderer.item.properties.selectCharge- A case based on the charge type of a crowssbow.ContextDimension- A case based on the dimension the item is currently within.ContextEntityType- A case based on the holding entity's type.CustomModelDataProperty- If the current index is set to the string withinDataComponents#CUSTOM_MODEL_DATA.DisplayContext- A case based on the display context.ItemBlockState- A case based on getting a property value from an item holding the block state properties.LocalTime- A case based on a simple date format pattern.MainHand- A case based on the arm holding the item.SelectItemModelProperties- Contains all potential select-cased property types.SelectItemModelProperty- Represents a property that returns some cased selection.TrimMaterialProperty- A case based on the trim material on the item.
net.minecraft.client.renderer.specialBannerSpecialRenderer- An item renderer for a banner.BedSpecialRenderer- An item renderer for a bed.ChestSpecialRenderer- An item renderer for a chest.ConduitSpecialRenderer- An item renderer for a conduit.DecoratedPotSpecialRenderer- An item renderer for a decorated pot.HangingSignSpecialRenderer- An item renderer for a hanging sign.NoDataSpecialModelRenderer- An item renderer that does not need to read any data from the stack.ShieldSpecialRenderer- An item renderer for a shield.ShulkerBoxSpecialRenderer- An item renderer for a shulker box.SkullSpecialRenderer- An item renderer for a skull.SpecialModelRenderer- Represents a model that reads data from the stack and renders the object without needing the render state.SpecialModelRenderers- Contains all potential special renderers.StandingSignSpecialRenderer- An item renderer for a standing sign.TridentSpecialRenderer- An item renderer for a trident.
net.minecraft.client.resources.modelBakedModelisCustomRendereris removed, replaced by the special renderer systemoverridesis removed, replaced by the properties renderer system
BlockStateModelLoaderno longer takes in the missing modeldefinitionLocationToBlockMapperis now privateloadBlockStateDefinitionStackis now privateloadBlockStates- Gets the loaded models for the block state.$LoadedBlockModelDefinitionis now package-private$LoadedModelnow takes in anUnbakedBlockStateModelinstead of aUnbakedModel$LoadedModelsforResolving- Returns all models hat need to be resolved.plainModels- Returns a map from the model location to the unbaked model.
BuiltInModelclass is removedClientItemInfoLoader- Loads all models for all item stacks.EquipmentModelSet->EquipmentAssetManagerItemModel->net.minecraft.client.renderer.item.ItemModelMissingBlockModel#MISSINGis now privateModelBakersprites- Returns the getter to get sprites.rootName- Gets the name of the model for debugging.
ModelBakery(Map<ModelResourceLocation, UnbakedModel>, Map<ResourceLocation, UnbakedModel>, UnbakedModel)->ModelBakery(EntityModelSet, Map<ModelResourceLocation, UnbakedBlockStateModel>, Map<ResourceLocation, ClientItem>, Map<ResourceLocation, UnbakedModel>, UnbakedModel)bakeModelsnow returns a$BakingResultgetBakedTopLevelModelsis removed$BakingResult- Holds all models that have been lodaded.$TextureGettergetnow takes in theModelDebugNameinstead of theModelResourceLocationreportingMissingReference- Handles how a texture is reported when not set.bind- Creates a spriate getter bound to the current model.
ModelDebugName- Returns the name of the model for debugging.ModelDiscoveryregisterStandardModelsis removedregisterSpecialModels- Adds the internal models loaded by the system.addRoot- Adds a new model that can be resolved.getUnreferencedModels- Returns the difference between the models loaded vs the models used.getTopModelsis removed
ModelGroupCollector$GroupKey#createnow takes in anUnbakedBlockStateModelinstead of aUnbakedModelModelManagerspecialBlockModelRenderer- Returns the renderer for special block models.entityModels- Returns the model set for the entities.getItemProeprties- Returns the properties for the client item based on its resource location.
ModelResourceLocation#inventoryis removedResolvableModel- The base model, usually unbaked, that have references to resolve.SimpleBakedModelfields are now all privatebakeElements- Bakes a model given the block elements.$Builderno longer has an overload that takes in theBlockModel
SpecialModelsclass is removedSpriteGetter- A getter for atlas sprites for the associated materials.UnbakedModelis now aResolvableModelbake(ModelBaker, Function<Material, TextureAtlasSprite>, ModelState)->bake(TextureSlots, ModelBaker, ModelState, boolean, boolean, ItemTransforms)getAmbientOcclusion,getTopAmbientOcclusion- Returns whether ambient occlusion should be enabled on the item.getGuiLight,getTopGuiLight- Returns the lighting side within a gui.getTransforms,getTopTransform,getTopTransforms- Returns the transformations to apply based on the display context.getTextureSlots,getTopTextureSlots- Returns the texture data for the model.getParent- Returns the parent of this model.bakeWithTopModelValues- Bakes the model.
net.minecraft.data.models.*->net.minecraft.client.data.models.*net.minecraft.world.itemBundleItemno longer takes in anyResourceLocationsopenFrontModel,openBackModelis removed
CrossbowItem$ChargeType- The item being charged by the crossbow.DyeColor#getMixedColor- Returns the dye most closely representing the mixed color.Item$Properties#overrideModelis removedSpawnEggItemno longer takes in its tint colorsgetColoris removed
net.minecraft.world.item.alchemy.PotionContentsgetColor(*)is removedgetColorOr- Gets a custom color fro the potion or the default if not present.
net.minecraft.world.item.component.CustomModelDatanow takes in a list of floats, flags, strings, and colors to use in the custom model properties based on the provided indexnet.minecraft.world.item.equipmentArmorMaterialnow takes in aResourceKey<EquipmentAsset>instead of just the model idEquipmentAsset- A marker to represent the equipment client info keyEquipmentAssets- All vanilla equipment assets.EquipmentModel->net.minecraft.client.resources.model.EquipmentClientInfoEquipmentModels->net.minecraft.client.data.models.EquipmentAssetProvider, not one-to-oneEquippablenow takes in aResourceKey<EquipmentAsset>instead of just the model id$Builder#setModel->setAsset
net.minecraft.world.item.equipment.trimArmorTrim#getTextureis removedTrimMaterialno longer takes in an item model index, and the key over the override armor materials points toResourceKey<EquipmentAsset>
net.minecraft.world.level.FoliageColorgetEvergreenColor->FOLIAGE_EVERGREENgetBirchColor->FOLIAGE_BIRCHgetDefaultColor->FOLIAGE_DEFAULTgetMangroveColor->FOLIAGE_MANGROVE
net.minecraft.world.level.block.RenderShape#ENTITYBLOCK_ANIMATEDis removednet.minecraft.world.level.block.entityBannerBlockEntity#fromItemis removedBedBlockEntitty#setColoris removedBlockEntity#saveToItemis removedDecoratedPotBlockEntity#setFromItem,getPotAsItemis removed
net.minecraft.world.level.storage.loot.functions.SetCustomModelDataFunctionnow takes in a list of floats, flags, strings, and colors to use in the custom model properties based on the provided index
Mob Replacing Current Items
One of the last hardcoded instances relating to tools and armor being subtypes of DiggerItem and ArmorItem, respectively, have been reworked: Mob#canReplaceCurrentItem. Now, it reads the EquipmentSlot of the stack from the DataComponents#EQUIPPABLE data component. Then, using that, different logic occurs depending on the situation.
For armor slots, it cannot be changed if the armor is enchanted with a EnchantmentEffectComponents#PREVENT_ARMOR_CHANGE effect component. Otherwise, it will attempt to compare the armor attributes first, then armor toughness if equal.
For weapons (via hand slots), it will first check if the mob has a preferred weapon type tag. If so, it will switch the item to the weapon in the tag, provided one item is in the tag and the other is not. Otherwise, it will attempt to compare attack damage attributes.
If all attributes are equal, then they will both default to the following logic. First, it will try to pick the item with the most enchantments. Then, it will attempt to pick the item with the most durability remaining (the raw value, not the percentage). Finally, it will check whether one of the items hsa a custom name via the DataComponents#CUSTOM_NAME.
As a small caveat,
BambooSaplingBlockandBambooStalkBLockstill hardcode a check for check if the mainhand item is aSwordItem, though this could probably be replaced with a change toToolMaterial#applySwordPropertiesin the future.
Particles, rendered through Render Types
Particles are now rendered using a RenderType, rather than setting a buffer builder themselves. The only special cases are ParticleRenderType#CUSTOM, which allows the modder to implement their own rendering via Particle#renderCustom; and ParticleRenderType#NO_RENDER, which renders nothing.
To create a new ParticleRenderType, it can be created by passing in its name for logging and the RenderType to use. Then, the type is returned in Particle#getRenderType.
public static final ParticleRenderType TERRAIN_SHEET_OPAQUE = new ParticleRenderType(
"TERRAIN_SHEET_OPAQUE", // Typically something recognizable, like the name of the field
RenderType.opaqueParticle(TextureAtlas.LOCATION_BLOCKS) // The Render Type to use
);
net.minecraft.client.particleCherryParticle->FallingLeavesParticle, not one-to-one as the new class has greater configuration for its generalizationItemPickupParticleno longer takes in theRenderBuffersParticle#renderCustom- Renders particles with theParticleRenderType#CUSTOMrender type.ParticleEngine#render(LightTexture, Camera, float)->render(Camera, float, MutliBufferSource$BufferSource)ParticleRenderTypeis now a record which takes in the name and theRenderTypeit uses.
Minor Migrations
The following is a list of useful or interesting additions, changes, and removals that do not deserve their own section in the primer.
SimpleJsonResourceReloadListener
SimpleJsonResourceReloadListeners now take in a converter to map some key to a resource location. An abstract has been provided for registry keys. This is done through a FileToIdConverter, which essentially holds a prefix and extension to apply to some ResourceLocation.
// We will assume this is a server reload listener (meaning in the 'data' folder)
public class MyLoader extends SimpleJsonResourceReloadListener<ExampleObject> {
public MyLoader() {
super(
// The codec to encode/decode the object
ExampleObject.CODEC,
// The file converter
// Will place files in data/<namespace>/example/object/<path>.json
FileToIdConverter.json(
// The prefix
"example/object"
)
);
}
// Below is the same
}
net.minecraft.server.packs.resources.SimpleJsonResourceReloadListenernow takes in a resource key for a registry, or a file to id converter instead of just a stringscanDirectorynow takes in a resource key for a registry, or a file to id converter instead of just a string
MetadataSectionSerializer, replaced by Codecs
MetadataSectionSerializer has been removed in favor of using Codecs to serialize the metadata sections. As such all MetadataSectionSerializers have been replaced by its MetadataSectionType instead, which holds the name of the section and the codec for the metadata section.
net.minecraft.client.renderer.textureHttpTexture->SkinTextureDownloader, not one-to-one as the new class is just a utility that returns the content to storeMissingTextureAtlasSpritegetTexture->generateMissingImage, not one-to-onegetMissingImage(int, int)is now public
SpriteLoader#loadAndStitchnow takes in a collection ofMetadataSectionTypes rather thanMetadataSectionSerializers
net.minecraft.client.resources.SkinManagerno longer takes in theTextureManagergetOrLoadnow returns anOptional<PlayerSkin>future instead of just thePlayerSkin
net.minecraft.client.resources.metadata.animationAnimationFrameis now a recordAnimationMetadataSectionis now a recordAnimationMetadataSectionSerializerclass is removedVillagerMetaDataSection->VillagerMetadataSectionVillagerMetadataSectionSerializerclass is removed
net.minecraft.client.resources.metadata.textureTextureMetadataSectionis now a recordTextureMetadataSectionSerializerclass is removed
net.minecraft.server.packs.PackResources#getMetadataSectionnow takes in aMetadataSectionTypeinstead of aMetadataSectionSerializernet.minecraft.server.packs.metadataMetadataSectionSerializeris removed in favor of section codecsMetadataSectionTypeis a now a record instead of aMetadataSectionSerializerextension
net.minecraft.server.packs.resources.ResourceMetadatagetSectionnow takes in aMetadataSectionTypeinstead of aMetadataSectionSerializercopySectionsnow takes in a collection ofMetadataSectionTypes instead of aMetadataSectionSerializers
Music, now with Volume Controls
The background music is now handled through a MusicInfo class, which also stores the volume along with the associated Music.
net.minecraft.client.Minecraft#getSituationalMusicnow returns aMusicInfoinstead of aMusicnet.minecraft.client.soundsMusicInfo- A record that holds the currently playingMusicand the volume its at.MusicManager#startPlayingnow takes in aMusicInfoinstead of aMusicSoundEngine#setVolume,SoundManager#setVolume- Sets the volume of the associated sound instance.
net.minecraft.world.level.biomeBiomegetBackgroundMusicnow returns a optionalSimpleWeightedRandomListof music.getBackgroundMusicVolume- Gets the volume of the background music.
BiomeSpecialEffects$Builder#silenceAllBackgroundMusic,backgroundMusic(SimpleWeightedRandomList<Music>)- Handles setting the background music for the biome.
Tag Changes
minecraft:blocktall_flowers->bee_attractive
minecraft:itemtall_flowers,flowersis removedtrim_templatesis removedskeleton_preferred_weaponsdrowned_preferred_weaponspiglin_preferred_weaponspillager_preferred_weaponswither_skeleton_disliked_weapons
List of Additions
com.mojang.blaze3d.platform.Window#isMinimized- Returns whether the application window is minimized.com.mojang.blaze3d.vertex.VertexBufferuploadStatic- Immediately uploads the provided vertex data via theConsumer<VertexConsumer>using theTesselatorwith aSTATIC_WRITEVertexBuffer.drawWithRenderType- Draws the current buffer to the screen with the givenRenderType.
com.mojang.math.MatrixUtil#isIdentity- Checks whether the currentMatrix4fis an identity matrix.net.minecraftSuppressForbidden- An annotation that holds some reason, usually related to needing the sysout stream.Util#maxAllowedExecutorThreads- Returns the number of available processors clamped between one and the maximum number of threads.
net.minecraft.client.gui.components.events.GuiEventListener#getBorderForArrowNavigation- Returns theScreenRectanglebound to the current direction.net.minecraft.client.gui.navigation.ScreenRectangle#transformAxisAligned- Creates a newScreenRectangleby transforming the position using the providedMatrix4f.net.minecraft.client.gui.narration.NarratableEntry#getNarratables- Returns the list of narratable objects within the current object.net.minecraft.client.gui.screens.recipebook.RecipeCollection#EMPTY- An empty collection of recipes.net.minecraft.client.gui.screens.worldselectionExperimentsScreen$ScrollArea- Represents a narratable scroll area of the currently available experiments.SwitchGrid#layout- Returns the layout of the grid to visit.
net.minecraft.client.modelBannerFlagModel,BannerModel- Models for the banner and hanging banner.VillagerLikeModel#translateToArms- Translates the pose stack such that the current relative position is at the entity's arms.
net.minecraft.client.model.geom.EntityModelSet#vanilla- Creates a new model set with all vanilla models.net.minecraft.client.multiplayer.PlayerInfo#setShowHat,showHat- Handles showing the hat layer of the player in the tab overlay.net.minecraft.client.renderer.blockentityAbstractSignRenderer- How a sign should render as a block entity.HangingSignRenderercreateSignModel- Creates a sign model given the wood and the attachment location.renderInHand- Renders the model in the entity's hand.$AttachmentType- An enum which represents where the model is attached to, given its properies.$ModelKey- A key for the model that combines theWoodTypewith its$AttachmentType.
SignRendererrenderInHand- Renders the model in the entity's hand.
net.minecraft.client.renderer.entity.EntityRenderer#getShadowStrength- Returns the raw opacity of the display's shadow.net.minecraft.client.renderer.entity.layers.CrossedArmsItemLayer#applyTranslation- Applies the translation to render the item in the model's arms.net.minecraft.client.renderer.textureReloadableTexture- A texture that can be reloaded from its associated contents.TextureContents- Holds the image and metadata associated with a given texture.TextureManagerregisterAndLoad- Registers a reloadable texture with the given name.registerForNextReload- Registers a texture by its resource location to be loaded on next reload.
net.minecraft.commands.SharedSuggestionProvider#MATCH_SPLITTER- Defines a matcher that matches a period, underscore, or forward slash.net.minecraft.core.BlockPos$TraversalNodeStatus- A marker indicating whether theBlockPosshould be used, skipped, or stopped from any further traversal.net.minecraft.core.component.PatchedDataComponentMaptoImmutableMap- Returns either the immutable patch or a copy of the current map.hasNonDefault- Returns whether there is a custom value for the data component instead of just the default.
net.minecraft.data.PackOutput$PathProvider#json- Gets the JSON path from a resource key.net.minecraft.data.loot.BlockLootSubProvider#createMultifaceBlockDrops- Drops a block depending on the block face mined.net.minecraft.data.worldgen.placement.PlacementUtils#HEIGHTMAP_NO_LEAVES- Creates a y placement using theHeightmap$Types#MOTION_BLOCKING_NO_LEAVESheightmap.net.minecraft.network.chat.Style#getShadowColor,withShadowColor- Methods for handling the shadow color of a component.net.minecraft.network.protocol.game.ServerboundPlayerLoadedPacket- A packet for when the client player loads into a client world.net.minecraft.resources.FileToIdConverter#registry- Gets the file converter from a registry key.net.minecraft.util.ExtraCodecsidResolverCodec- Creates a codec that maps some key to some value.compactListCodec- Creates a codec that can either be an element of a list of elements.floatRange- Creates a codec that must be between two float values.$LateBoundIdMapper- A mapper that functionally acts like a registry with an associated codec.
net.minecraft.util.profiling.jfr.JvmProfiler#onStructureGenerate- Returns the profiled duration on when a structure attempts to generate in the world.net.minecraft.util.profiling.jfr.event.StructureGenerationEvent- A profiler event when a structure is being generated.net.minecraft.util.profiling.jfr.stats.StructureGenStat- A result of a profiled structure generation.net.minecraft.world.entityLivingEntityresolvePlayerResponsibleForDamage- Gets the player responsible for hurting the current entity.canBeNameTagged- When true, the entity's can be set with a name tag.
Mob#getPreferredWeaponType- Gets the tag that represents the weapons the entity wants to pick up.
net.minecraft.world.entity.ai.attributes.AttributeMap#resetBaseValue- Resets the attribute instance to its default value.net.minecraft.world.entity.monster.creakingCreakingactivate,deactivate- Handles the activateion of the brain logic for the creaking.setTransient,isHeartBound,setHomePos,getHomePos- Handles the home position.blameSourceForDamage- Finds the player responsible for the damage.tearDown- Handles when the creaking is destroyed.creakingDeathEffects- Handles the death of a creaking.playerIsStuckInYou- Checks whether there are at least four players stuck in a creaking.setTearingDown,isTearingDown- Handles the tearing down state.hasGlowingEyes,checkEyeBlink- Handles the eye state.
net.minecraft.world.entity.player.PlayerhasClientLoaded,setClientLoaded- Whether the client player has been loaded.tickClientLoadTimeout- Ticks the timer on how long to wait before kicking out the client player if not loaded.
net.minecraft.world.itemItem#shouldPrintOpWarning- Whether a warning should be printed to the player based on stored block entity data and adminstrator permissions.ItemStackgetCustomName- Returns the custom name of the item, ornullif no component exists.immutableComponents- Returns either the immutable patch or a copy of the stack component map.hasNonDefault- Returns whether there is a custom value for the data component instead of just the default.
net.minecraft.world.item.component.CustomDataparseEntityId- Reads the entity id off of the component.parseEntityType- Reads the entity type from the id and maps it to its registry object.
net.minecraft.world.item.crafting.Ingredient#isEmpty- Returns whether the ingredient has no values.net.minecraft.world.item.trading.Merchant#stillValid- Checks whether the merchant can still be accessed by the player.net.minecraft.world.levelLevel#dragonParts- Returns the list of entities that are the parts of the ender dragon.ServerExplosion#getDamageSource- Returns the damage source of the explosion.
net.minecraft.world.level.blockEyeblossomBlock$Typeblock- Gets the block for the current type.state- Gets the block state for the current type.transform- Returns the opposiate state of this type.
FlowerBlock#getBeeInteractionEffect- Returns the effect that bees obtain when interacting with the flower.FlowerPotBlock#opposite- Returns the opposite state of the block, only for potted eyeblossoms.MultifaceBlock#canAttachTo- Returns whether this block can attach to another block.MultifaceSpreadeableBlock- A multiface block that can naturally spread.
net.minecraft.world.level.block.entity.trialspawnerTrialSpawner#overrideEntityToSpawn- Changes the entity to spawn in the trial.TrialSpawnerConfig#withSpawning- Sets the entity to spawn within the trial.
List of Changes
com.mojang.blaze3d.platform.NativeImage#uploadno longer takes in three booleans that set the filter mode or texture wrap clamping forTEXTURE_2D- This has been moved to
AbstractTexture#setClampand#setFilter
- This has been moved to
net.minecraft.client.guiGui#clear->clearTitlesGuiGraphics#drawWordWraphas a new overload that takes in whether a drop shadow should be applied to the text- The default version enables drop shadows instead of disabling it
net.minecraft.client.gui.componentsAbstractContainerWidgetnow implementsAbstractScrollAreaAbstractScrollWidget->AbstractScrollAreaorAbstractTextAreaWidgetdepending on use-case, not one-to-oneAbstractSelectionListsetRenderHeaderis now bundled into a new constructor with an extra integergetMaxScroll->AbstractScrollArea#maxScrollAmountgetScrollAmount->AbstractScrollArea#scrollAmountscrollbarVisible->AbstractScrollArea#scrollbarVisiblesetClampedScrollAmount,setScrollAmount->AbstractScrollArea#setScrollAmountclampScrollAmount->refreshScrollAmountupdateScrollingState->AbstractScrollArea#updateScrollinggetScrollbarPosition,getDefaultScrollbarPosition->scrollBarY, not one-to-one
AbstractWidget#clicked->isMouseOver, already exists
net.minecraft.client.gui.components.toasts.TutorialToastnow requires aFontas the first argument in its constructornet.minecraft.client.gui.font.glyphs.BakedGlyph$Effectand$GlyphInstancenow take in the color and offset of the text shadownet.minecraft.client.gui.screensLoadingOverlay#registerTexturesnow takes in aTextureManagerinstead of theMinecraftinstanceTitleScreen#preloadResources->registerTextures, not one-to-one
net.minecraft.client.gui.screens.debug.GameModeSwitcherScreen$GameModeSlotis now a static inner classnet.minecraft.client.gui.screens.reporting.ChatSelectionScreen$Entry,$PaddingEntryare now static inner classesnet.minecraft.client.gui.screens.worldselection.SwitchGrid$Builder#buildno longer takes in aConsumer<LayoutElement>net.minecraft.client.modelDonkeyModel#createBodyLayer,createBabyLayernow take in a scaling factorVillagerHeadModel->VillagerLikeModel
net.minecraft.client.model.geom.EntityModelSetis no longer aResourceManagerReloadListenernet.minecraft.client.multiplayer.MultiPlayerGameMode#handlePickItem->handlePickItemFromBlockorhandlePickItemFromEntity, providing both the actual object data to sync and abooleanabout whether to include the data of the object being pickednet.minecraft.client.particle.CherryParticle->FallingLeavesParticle, not one-to-one as the new class has greater configuration for its generalizationnet.minecraft.client.player.ClientInput#tickno longer takes in any parametersnet.minecraft.client.rendererCubeMap#preload->registerTextures, not one-to-oneLevelRendererrenderLevelno longer takes in theLightTextureonChunkLoaded->onChunkReadyToRender
PostChainConfig$Pass#program->programIdprogramnow returns theShaderProgramwith the givenprogramId
ScreenEffectRenderer#renderScreenEffectnow takes in aMultiBufferSourceSectionOcclusionGraph#onChunkLoaded->onChunkReadyToRenderSheets#createSignMaterial,createHangingSignMaterialnow has an overload that takes in aResourceLocationSkyRendererrenderSunMoonAndStars,renderSunriseAndSunsetnow takes in aMultiBufferSource$BufferSourceinstead of aTesselatorrenderEndSkyno longer takes in thePoseStack
WeatherEffectRenderer#rendernow takes in aMultiBufferSource$BufferSourceinstead of aLightTexture
net.minecraft.client.renderer.blockentityBannerRenderer#createBodyLayer->BannerModel#createBodyLayer, not one-to-oneHangingSignRenderercreateHangingSignLayernow takes in aHangingSignRenderer$AttachmentType$HangingSignModelis now replaced with aModel$Simple, though its fields can be obtained from the root
SkullBlockRenderer#getRenderTypenow has an overload that takes in aResourceLocationto override representing the player's texture
net.minecraft.client.renderer.entity.AbstractHorseRenderer,DonkeyRendererno longer takes in a float scalenet.minecraft.client.renderer.entity.layers.CrossedArmsItemLayernow requires the genericMto be aVillagerLikeModelnet.minecraft.client.renderer.entity.state.CreakingRenderState#isActive->eyesGlowing- The original parameter still exists on the
Creaking, but is not necessary for rendering
- The original parameter still exists on the
net.minecraft.core.BlockPos#breadthFirstTraversalnow takes in a function that returns a$TraversalNodeStatusinstead of a simple predicate to allow certain positions to be skippednet.minecraft.core.particles.TargetColorParticleOption->TrailParticleOption, not one-to-onenet.minecraft.data.DataProvider#savelAllnow has overloads for maps with a key function to get the associated pathnet.minecraft.networkNoOpFrameEncoderreplaced byLocalFrameEncoder, not one-to-oneNoOpFrameDecoderreplaced byLocalFrameDecoder, not one-to-oneMonitorFrameDecoderreplaced byMonitoredLocalFrameDecoder, not one-to-one
net.minecraft.network.protocol.gameClientboundLevelParticlesPacketnow takes in a boolean that determines whether the particle should always renderClientboundMoveVehiclePacketis now a recordClientboundPlayerInfoUpdatePacket$Entrynow takes in a boolean representing whether the hat should be shownClientboundSetHeldSlotPacketis now a recordServerboundMoveVehiclePacketis now a recordServerboundPickItemPacket->ServerboundPickItemFromBlockPacket,ServerboundPickItemFromEntityPacket; not one-to-one
- `net.minecraft.server.level
ServerLevel#sendParticlesnow has an overload that takes in the override limiter distance and whether the particle should always be shown- Other overloads that take in the override limiter now also take in the boolean for if the particle should always be shown
ServerPlayer#doCheckFallDamage->Entity#doCheckFallDamage, now final
net.minecraft.utilARGB#from8BitChannelis now private, with individual float components obtained fromalphaFloat,redFloat,greenFloat, andblueFloatSpawnUtil#trySpawnMobnow takes in a boolean that, when false, allows the entity to spawn regardless of collision status with the surrounding area
net.minecraft.util.profiling.jfr.callback.ProfiledDuration#finishnow takes in a boolean that indicates whether the profiled event was successfulnet.minecraft.util.profiling.jfr.parse.JfrStatsResultsnow takes in a list of structure generation statisticsnet.minecraft.world.effect.PoisonMobEffect,WitherMobEffectis now publicnet.minecraft.world.entityEntitysetOnGroundWithMovementhas an overload that sets the horizontal collision to whatever the entity's current state is.awardKillScoreno longer takes in an integermakeBoundingBox()is now finalmakeBoundingBox(Vec3)is now
onlyOpCanSetNbt->EntityType#onlyOpCanSetNbt
LeashablereadLeashDatais now private, replaced by a method that returns nothingdropLeash(boolean, boolean)->dropLeash(),removeLeash,onLeashRemoved; not one-to-one, as they all internally call the privatedropLeash
LivingEntityisLookingAtMeno longer takes in aPredicate<LivingEntity>, and array ofDoubleSuppliers is now an array ofdoubleshasLineOfSighttakes in a double instead of aDoubleSupplier
net.minecraft.world.entity.ai.behavior.AcquirePoi#createnow has overloads which take in aBiPredicate<ServerLevel, BlockPos>for filtering POI locationsnet.minecraft.world.entity.animal.Bee#attractsBeesis now publicnet.minecraft.world.entity.monster.Shulker#getProgressAabb,getProgressDeltaAabbnow take in a movementVec3net.minecraft.world.entity.playerInventorysetPickedItem->addAndPickItemfindSlotMatchingCraftingIngredientnow takes in anItemStackto compare against
Player#getPermissionLevelis now publicStackedContents$IngredientInfois now an interface that acts like a predicate for accepting some item
net.minecraft.world.entity.projectile.FishingHookno longer takes in theItemStacknet.minecraft.world.inventory.Slot#getNoItemIconnow returns a singleResourceLocationrather than a pair of themnet.minecraft.world.itemItem$TooltipContext#ofnow takes in thePlayerviewing the itemMobBucketItemnow requires aMobentity type -SpawnEggItem#spawnsEntity,getTypenow takes in aHolderLookup$Provider
net.minecraft.world.item.craftingIngredientnow implementsStackedContents$IngredientInfo<Holder<Item>>itemsnow returns a stream instead of a list
PlacementInfo#slotInfo->slotsToIngredientIndex, not one-to-one
net.minecraft.world.level.Level#addParticlenow takes in a boolean representing if the particle should always be shownnet.minecraft.world.level.blockBlock#getCloneItemStack->state.BlockBehaviour#getCloneItemStack, now protectedCherryLeavesBlock->ParticleLeavesBlockCreakingHeartBlock#canSummonCreaking->isNaturalNightMultifaceBlockis no longer abstract and implementsSimpleWaterloggedBlockgetSpreader->MultifaceSpreadeableBlock#getSpreader
SculkVeinBlockis now an instance ofMultifaceSpreadeableBlockSnowyDirtBlock#isSnowySettingis now protected
net.minecraft.world.level.block.entityAbstractFurnaceBlockEntitylitTime->litTimeRemaininglitDuration->litTotalTimecookingProgress->cookingTimer
BeehiveBlockEntity#addOccupantnow takes in aBeerather than anEntityCreakingHeartBlockEntity#setCreakingInfo- Sets the creaking the block entity is attached to.
net.minecraft.world.level.block.state.BlockBehaviour#getCloneItemStack,$BlockStateBase#getCloneItemStacknow takes in a boolean representing if there is infinite materials and whether the current block data should be saved.net.minecraft.world.level.chunk.ChunkGenerator#createStructuresnow takes in theLevelresource key, only used for profilingnet.minecraft.world.level.levelgen.feature.configurationsMultifaceGrowthConfigurationnow takes in aMultifaceSpreadableBlockinstead of aMultifaceBlockSimpleBlockConfigurationnow takes in a boolean on whether to schedule a tick update
net.minecraft.world.level.levelgen.structure.Structure#generatenow takes in theStructureholder and aLevelresource key, only used for profiling
List of Removals
com.mojang.blaze3d.systems.RenderSystem#overlayBlendFuncnet.minecraft.client.gui.components.AbstractSelectionListclickedHeaderisValidMouseClick
net.minecraft.client.gui.screens.recipebook.RecipeCollection#hasSingleResultItemnet.minecraft.client.modelDrownedModel#getArmPose, now part of theArmedEntityRenderStateFelineModel#CAT_TRANSFORMERHumanoidModel#getArmPose, now part of theArmedEntityRenderStatePlayerModel#getArmPose, now part of theArmedEntityRenderStateSkeletonModel#getArmPose, now part of theArmedEntityRenderStateVillagerModel#BABY_TRANSFORMER
net.minecraft.client.renderer.textureAbstractTextureloadresetgetDefaultBlur
PreloadedTextureTextureManagergetTexture(ResourceLocation, AbstractTexture)register(String, DynamicTexture)preload
net.minecraft.server.level.TicketType#POST_TELEPORTnet.minecraft.world.entity.LivingEntity#deathScorenet.minecraft.world.entity.ai.navigation.FlyingPathNavigation,GroundPathNavigationcanPassDoors,setCanPassDoorscanOpenDoors
net.minecraft.world.entity.monster.creaking.CreakingTransientnet.minecraft.world.entity.player.StackedItemContents#convertIngredientContentsnet.minecraft.world.itemCompassItem#getSpawnPositionItemStack#clearComponents
net.minecraft.world.item.crafting.PlacementInfoingredientToContentsunpackedIngredients$SlotInfo
net.minecraft.world.level.block.CreakingHeartBlock$CreakingHeartStatenet.minecraft.world.level.block.entity.BlockEntity#onlyOpCanSetNbtnet.minecraft.world.level.block.entity.trialspawner.TrialSpawnerData#setEntityId