Minecraft 1.21.4 -> 1.21.5 Mod Migration Primer
This is a high level, non-exhaustive overview on how to migrate your mod from 1.21.4 to 1.21.5. 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.
Thank you to:
- @TelepathicGrunt for the information within the 'Very Technical Changes' section
- @RogueLogix for their review and comments on the 'Render Pipeline Rework' section
- @Tslat for catching an error about
equipOnInteract
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.
Handling the Removal of Block Entities Properly
Previously, BlockEntity would handle all of their removal logic within BlockBehaviour#onRemove, including both dropping any stored items and removing the block entity itself. However, depending on how the method is used, it can cause some strange behaviors due to the mutable state of the block entity. For this reason, the logic that makes up the removal process has been split between two methods: BlockEntity#preRemoveSideEffects and BlockBehaviour#affectNeighborsAfterRemoval.
BlockEntity#preRemoveSideEffects is now responsible for removing anything from the block entity before it is removed from the level. By default, if the BlockEntity is a Container instance, it will drop the contents of the container into the level. Other logic can be handled within here, but it should generally avoid removing the BlockEntity itself, unless the position of the block entity tends to change dynamically, like for a piston.
From there, the LevelChunk logic will call removeBlockEntity before calling BlockBehaviour#affectNeighborsAfterRemoval. This should only send the updates to other blocks indicating that this block has been removed from the level. For BlockEntity holders, this can be done easily by calling Containers#updateNeighboursAfterDestroy. Otherwise may want to call Level#updateNeighborsAt themselves, depending on the situation.
net.minecraft.world.ContainersupdateNeighboursAfterDestroy- Updates the neighbor state aftering destroying the block at the specified position.dropContentsOnDestroyis removed, handled withinBlockEntity#preRemoveSideEffectsforContainerinstances
net.minecraft.world.level.block.entity.BlockEntity#preRemoveSideEffects- Handles logic on the block entity that should happen before being removed from the level.net.minecraft.world.level.block.state.BlockBehaviour#onRemove,$BlockStateBase#onRemove->affectNeighborsAfterRemoval, should only handle logic to update the surrounding neighbors rather than dropping container data
Voxel Shape Helpers
VoxelShapes have received numerous helpers for more common transformations of its base state. There are the Block methods for creating a centered (if desired) box and the Shapes methods for rotating a VoxelShape to its appropriate axis or direction. There is also a Shapes#rotateAttachFace method for rotating some VoxelShape that is attached to a face of a different block. The results are either stored in a Map of some key to a VoxelShape, or when using Block#getShapeForEachState, a Function<BlockState, VoxelShape>.
Most of the Block subclasses that had previous public or protected VoxelShapes are now private, renamed to a field typically called SHAPE or SHAPES. Stored VoxelShapes may also be in a Function instead of directly storing the map itself.
com.mojang.math.OctahedralGrouppermute- Returns the axis that the given axis is permuted to within the specified group.fromAngles- Creates a group with the provided X and Y rotations.
net.minecraft.core.Direction$Axis#choosenow has an overload that takes in three booleansnet.minecraft.world.level.block.Blockboxes- Creates one more than the specified number of boxes, using the index as part of the function to create theVoxelShapes.cube- Creates a centered cube of the specified size.column- Creates a horizontally centered column of the specified size.boxZ- Creates a vertically centered (around the X axis) cube/column of the specified size.getShapeForEachStatenow returns aFunctionwhich wraps theImmutableMap, there is also a method that only considers the specified properties instead of all possible states.
net.minecraft.world.phys.shapesDiscreteVoxelShape#rotate- Rotates a voxel shape according to the permutation of theOctahedralGroup.ShapesblockOccudes->blockOccludesrotate- Rotates a given voxel shape according to the permutation of theOctahedralGrouparound the provided vector, or block center if not specified.equal- Checks if two voxel shapes are equivalent.rotateHorizontalAxis- Creates a map of axes toVoxelShapes of a block being rotated around the y axis.rotateAllAxis- Creates a map of axes toVoxelShapes of a block being rotated around any axis.rotateHorizontal- Creates a map of directions toVoxelShapes of a block being rotated around the y axis.rotateAll- Creates a map of directions toVoxelShapes of a block being rotated around the any axis.rotateAttachFace- Creates a map of faces to a map of directions toVoxelShapes of a block being rotated around the y axis when attaching to the faces of other blocks.
VoxelShape#movenow has an overload to take in aVec3i
Weapons, Tools, and Armor: Removing the Redundancies
There have been a lot of updates to weapons, tools, and armor that removes the reliance on the hardcoded base classes of SwordItem, DiggerItem, and ArmorItem, respectively. These have been replaced with their associated data components WEAPON for damage, TOOL for mining, ARMOR for protection, and BLOCKS_ATTACKS for shields. Additionally, the missing attributes are usually specified by setting the ATTRIBUTE_MODIFIERS, MAX_DAMAGE, MAX_STACK_SIZE, DAMAGE, REPAIRABLE, and ENCHANTABLE. Given that pretty much all of the non-specific logic has moved to a data component, these classes have now been completely removed. Use one of the available item property methods or call Item$Properties#component directly to set up each item as a weapon, tool, armor, or some combination of the three.
Constructing a BlockAttacks component for a shield-like item:
var blocker = new BlocksAttacks(
// The number of seconds to wait when the item is being used
// before the blocking effect is applied.
1.2f,
// A scalar to change how many ticks the blocker is disabled
// for. If negative, the blocker cannot normally be disabled.
0.5f,
// A list of reductions for what type and how much of a damage type
// is blocked by this blocker.
List.of(
new DamageReduction(
// The horizontal blocking angle of the shield required to apply
// the reduction
90f,
// A set of damage types this reduction should apply for.
// When empty, it applies for all damage types.
Optional.empty(),
// The base damage to reduce the attack by.
1f,
// A scalar representing the fraction of the damage blocked.
0.5f
)
),
// A function that determines how much durability to remove to the blocker.
new ItemDamageFunction(
// A threshold that specifies the minimum amount of damage required
// to remove durability from the blocker.
4f,
// The base durability to remove from the blocker.
1f,
// A scalar representing the fraction of the damage to convert into
// removed durability.
0.5f
),
// A tag key containing the items that can bypass the blocker and deal
// damage directly to the wielding entity. If empty, no item can bypass
// the blocker.
Optional.of(DamageTypeTags.BYPASSES_SHIELD),
// The sound to play when the blocker successfully mitigates some damage.
Optional.of(SoundEvents.SHIELD_BLOCK),
// The sound to play when the blocker is disabled by a weapon.
Optional.of(SoundEvents.SHIELD_BREAK)
);
Constructing a Weapon component for a sword-like item:
var weapon = new Weapon(
// The amount of durability to remove from the item.
3,
// The number of seconds a `BlocksAttack`s component item should
// be disabled for when hit with this weapon.
5f
);
net.minecraft.core.component.DataComponentsUNBREAKABLEis now aUnitinstanceHIDE_ADDITIONAL_TOOLTIP,HIDE_TOOLTIPhave been bundled inTOOLTIP_DISPLAY, taking in aTooltipDisplayBLOCKS_ATTACKS- A component that determines whether a held item can block an attack from some damage sourceINSTRUMENTnow takes in anInstrumentComponentPROVIDES_TRIM_MATERIAL,PROVIDES_BANNER_PATTERNShandles a provider for their associated types.BEESnow takes in aBeescomponentBREAK_SOUND- The sound to play when the item breaks.
net.minecraft.data.recipesRecipeProvider#trimSmithingnow takes in the key for theTrimPatternSmithingTrimRecipeBuildernow takes in a holder for theTrimPattern
net.minecraft.world.entity.LivingEntityblockUsingShield->blockUsingItemblockedByShield->blockedByItemhurtCurrentlyUsedShieldis removedcanDisableBlocking->getSecondsToDisableBlocking, not one-to-oneapplyItemBlocking- Applies the damage reduction done when blocking an attack with an item.isDamageSourceBlockedis removed
net.minecraft.world.entity.player.Player#disableShield->net.minecraft.world.item.component.BlocksAttacks#disablenet.minecraft.world.itemAnimalArmorItemclass is removedArmorItemclass is removedAxeItemnow extendsItemBannerPatternItemclass is removedDiggerItemclass is removedFireworkStarItemclass is removedHoeItemnow extendsItemInstrumentItemno longer takes in the tag keyItemgetBreakingSoundis removed$Propertiestool- Sets the item as a tool.pickaxe- Sets the item as a pickaxe.sword- Sets the item as a sword.axe- Sets the item as an axe.hoe- Sets the item as a hoe.shovel- Sets the item as a shovel.trimMaterial- Sets the item as providing a trim material.
ItemStack#getBreakingSoundis removedPickaxeItemclass is removedShovelItemnow extendsItemSwordItemclass is removedToolMaterial#applyToolPropertiesnow takes in a boolean of whether the weapon can disable a blocker (e.g., shield)
net.minecraft.world.item.componentBees- A component that holds the occupants of a beehive.BlocksAttacks- A component for blocking an attack with a held item.InstrumentComponent- A component that holds the sound an instrument plays.ProvidesTrimMaterial- A component that provides a trim material to use on some armor.Toolnow takes in a boolean representing if the tool can destroy blocks in creativeUnbreakableclass is removedWeapon- A data component that holds how much damage the item can do and for how long it disables blockers (e.g., shield).
net.minecraft.world.item.equipmentAllowedEntitiesProvider- A functional interface for getting the entities that are allowed to handle the associated logic.ArmorMaterialhumanoidProperties->Item$Properties#humanoidArmoranimalProperties->Item$Properties#wolfArmor,horseArmorcreateAttributesis now public
EquippableequipOnInteract- When true, the item can be equipped to another entity when interacting with them.saddle- Creates an equippable for a saddle.equipOnTarget- Equips the item onto the target entity.
Extrapolating the Saddles: Equipment Changes
A new EquipmentSlot has been added for saddles, which brings with it new changes for genercizing slot logic.
First, rendering an equipment slot for an entity can now be handled as an additional RenderLayer called SimpleEquipmentLayer. This takes in the entity renderer, the EquipmentLayerRenderer, the layer type to render, a function to get the ItemStack from the entity state, and the adult and baby models. The renderer will attempt to look up the client info from the associated equippable data component and use that to render the laters as necessary.
Next, instead of having individual lists for each equipment slot on the entity, there is now a general EntityEquipment object that holds a delegate to a map of slots to ItemStacks. This simplifies the storage logic greatly.
Finally, equippables can now specify whether an item should be equipped to a mob on interact (usually right-click) by setting equipOnInteract.
net.minecraft.client.modelCamelModelheadis now publiccreateBodyMesh- Creates the mesh definition for a camel.
CamelSaddleModel- A model for a camel with a saddle.DonkeyModel#createSaddleLayer- Creates the layer definition for a donkey with a saddle.EquineSaddleModel- A model for an equine animal with a saddle.PolarBearModel#createBodyLayernow takes in a boolean for if the entity is a baby
net.minecraft.client.renderer.entity.layers.HorseArmorLayer,SaddleLayer->SimpleEquipmentLayernet.minecraft.client.renderer.entity.stateCamelRenderState#isSaddled->saddle, not one-to-oneEquineRenderState#isSaddled->saddle, not one-to-onePigRenderState#isSaddled->saddle, not one-to-oneSaddleableRenderStateclass is removedStriderRenderState#isSaddled->saddle, not one-to-oneCamelRenderState#isSaddled->saddle, not one-to-one
net.minecraft.client.resources.model.EquipmentClientInfo$LayerTypenow has:PIG_SADDLESTRIDER_SADDLECAMEL_SADDLEHORSE_SADDLEDONKEY_SADDLEMULE_SADDLEZOMBIE_HORSE_SADDLESKELETON_HORSE_SADDLEtrimAssetPrefix- Returns the prefix applied to the texture containing the armor trims for the associated type.
net.minecraft.world.entityEntityEquipment- A map of slots to item stacks representing the equipment of the entity.EquipmentSlotSADDLE,$Type#SADDLEcanIncreaseExperience- Whether the slot can increase the amount of experience earned when killing a mob.
EquipmentSlotGroupis now an iterableSADDLEslots- Returns the slots within the group.
LivingEntitygetEquipSound- Gets the sound to play when equipping an item into a slot.getArmorSlots,getHandSlots,getArmorAndBodyArmorSlots,getAllSlotsare removedequipment- The equipment worn by the entity.createEquipment- Sets the default equipment worn by the entity.drop- Drops the specified stack.getItemBySlot,setItemBySlotare no longer abstract.verfiyEquippedItemis removed
MobisSaddled- Checks if an item is in the saddle slot.createEquipmentSlotContainer- Creates a single item container for the equipment slot.
OwnableEntity#getRootOwner- Gets the highest level owner of the entity.Saddleableinterface is removed
net.minecraft.world.entity.animal.horse.AbstractHorsesyncSaddletoClientsis removedgetBodyArmorAccessis removed
net.minecraft.world.entity.playerInventoryarmor,offhand->EQUIPMENT_SLOT_MAPPING, not one-to-oneselectedis now privatesetSelectedHotbarSlot->setSelectedSlot- Getter also exists
getSelectedSlot
- Getter also exists
getSelected->getSelectedItem- Setter also exists
setSelectedItem
- Setter also exists
getNonEquipmentItems- Returns the list of non-equipment items in the inventory.getDestroySpeedis removedgetArmoris removed
PlayerEquipment- Equipment that is worn by the player.
net.minecraft.world.itemItem#inventoryTick(ItemStack, Level, Entity, int, boolean)->inventoryTick(ItemStack, ServerLevel, Entity, EquipmentSlot)SaddleItemclass is removed
Weighted List Rework
The weighted random lists have been redesigned into a basic class that hold weighted entries, and a helper class that can obtain weights from the objects themselves.
First there is WeightedList. It is effectively the replacement for SimpleWeightedRandomList, working the exact same way by storing Weighted (replacement for WeightedEntry) entries in the list itself. Internally, the list is either stored as a flat array of object entries, or the compact weighted list if the total weight is greater than 64. Then, to get a random element, either getRandom or getRandomOrThrow can be called to obtain an entry. Both of these methods will either return some form of an empty object or exception if there are no elements in the list.
Then there are the static helpers within WeightedRandom. These take in raw lists and some ToIntFunction that gets the weight from the list's object. Some methods also take in an integer either representing the largest index to choose from or the entry associated with the weighted index.
net.minecraft.client.resources.model.WeightedBakedModelnow takes in aWeightedListinstead of aSimpleWeightedRandomListnet.minecraft.util.randomSimpleWeightedRandomList,WeightedRandomList->WeightedList, now final and not one-to-onecontains- Checks if the list contains this element.
Weightclass is removedWeightedEntry->Weighted- All
WeightedRandomstatic methods now take in aToIntFunctionto get the weight of some entry within the provided list
net.minecraft.util.valueproviders.WeightedListIntnow takes in aWeightedListnet.minecraft.world.level.SpawnData#LIST_CODECis now aWeightedListofSpawnDatanet.minecraft.world.level.biomeBiome#getBackgroundMusicis now aWeightedListofMusicBiomeSpecialEffects#getBackgroundMusic,$Builder#backgroundMusicis now aWeightedListofMusicMobSpawnSettings#EMPTY_MOB_LIST,getMobsis now aWeightedList
net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig#spawnPotentialsDefinition,lootTablesToEjectnow takes in aWeightedListnet.minecraft.world.level.chunk.ChunkGenerator#getMobsAtnow returns aWeightedListnet.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvidernow works withWeightedListsnet.minecraft.world.level.levelgen.heightproviders.WeightedListHeightnow works withWeightedListsnet.minecraft.world.level.levelgen.structure.StructureSpawnOverridenow takes in aWeightedListnet.minecraft.world.level.levelgen.structure.pools.aliasPoolAliasBinding#random,randomGroupnow takes in aWeightedListRandomnow takes in aWeightedListRandomGroupnow takes in aWeightedList
net.minecraft.world.level.levelgen.structure.structures.NetherFortressStructure#FORTRESS_ENEMIESis now aWeightedList
Tickets
Tickets have been reimplemented into a half type registry-like, half hardcoded system. The underlying logic of keeping a chunk loaded or simulated for a certain period of time still exists; however, the logic associated with each ticket is hardcoded into their appropriate locations, such as the forced or player loading tickets.
Tickets begin with their registered TicketType, which contains information about how many ticks should the ticket should last for (or 0 when permanent), whether the ticket should be saved to disk, and what the ticket is used for. A ticket has two potential uses: one for loading the chunk and keeping it loaded, and one for simulating the chunk based on the expected movement of the ticket creator. Most ticks specify that they are for both loading and simulation.
There are two special types that have additional behavior associated with them. TicketType#FORCED has some logic for immediately loading the chunk and keeping it loaded. TicketType#UNKNOWN cannot be automatically timed out, meaning they are never removed unless explicitly specified.
// You need to register the ticket type to `BuiltInRegistries#TICKET_TYPE`
public static final TicketType EXAMPLE = new TicketType(
// The amount of ticks before the ticket is removed
// Set to 0 if it should not be removed
0L,
// Whether the ticket should be saved to disk
true,
// What the ticket will be used for
TicketType.TicketUse.LOADING_AND_SIMULATION
);
Then there is the Ticket class, which are actually stored and handled within the TicketStorage. The Ticket class takes in the type of the ticket and uses it to automatically populate how long until it expires. It also takes in the ticket level, which is a generally a value of 31 (for entity ticking and block ticking), 32 (for block ticking), or 33 (only can access static or modify, not naturally update) minus the radius of chunks that can be loaded. A ticket is then added to the process by calling TicketStorage#addTicketWithRadius or its delegate ServerChunkCache#addTicketWithRadius. There is also addTicket if you wish to specify the ticket manually rather than having it computed based on its radius.
net.minecraft.server.levelChunkMapnow takes in aTicketStorage$TrackedEntity#broadcastIgnorePlayers- Broadcasts the packet to all player but those within the UUID list.
DistanceManagerchunksToUpdateFuturesis now protected and takes in aTicketStoragepurgeStaleTickets->net.minecraft.world.level.TicketStorage#purgeStaleTicketsgetTicketDebugString->net.minecraft.world.level.TicketStorage#getTicketDebugStringgetChunkLevel- Returns the current chunk level or the simulated level when the provided boolean is true.getTickingChunksis removedremoveTicketsOnClosingis removed$ChunkTicketTracker->LoadingChunkTracker, orSimulationChunkTracker
ServerChunkCacheaddRegionTicket->addTicketWithRadius, oraddTicketremoveRegionTicket->removeTicketWithRadiusremoveTicketsOnClosing->deactivateTicketsOnClosing
Ticketis no longer final or implementsComparable- The constructor no longer takes in a key
CODECsetCreatedTick,timedOut->resetTicksLeft,decreaseTicksLeft,isTimedOut; not one-to-one
TicketTypeis now a record and no longer has a genericgetComparatoris removeddoesLoad,doesSimulate- Checks whether the ticket use is for their particular instance.$TicketUse- What a ticket can be used for.
TickingTracker->SimulationChunkTracker
net.minecraft.world.level.ForcedChunksSavedData->TicketStoragenet.minecraft.world.level.chunk.ChunkSourceupdateChunkForcednow returns a boolean indicating if the chunk has been forcefully loadedgetForceLoadedChunks- Returns all chunks that have been forcefully loaded.
The Game Test Overhaul
Game tests have been completely overhauled into a registry based system, completely revamped from the previous automatic annotation-driven system. However, most implementations required to use the system must be implemented yourself rather than provided by vanilla. As such, this explanation will go over the entire system, including which parts need substantial work to use it similarly to the annotation-driven system of the previous version.
The Environment
All game tests happen within some environment. Most of the time, a test can occur independent of the area, but sometimes, the environment needs to be curated in some fashion, such as checking whether an entity or block does something at a given time or whether. To facilitate the setup and teardown of the environment for a given test instance, a TestEnvironmentDefinition is created.
A TestEnvironmentDefinition works similarly to the BeforeBatch and AfterBatch annotations. The environment contains two methods setup and teardown that manage the ServerLevel for the test. The environments are structured in a type-based registry system, meaning that every environment registers a MapCodec to built-in registry minecraft:test_environment_definition_type that is then consumed via the TestEnvironmentDefinition in a datapack registry minecraft:test_environment.
Vanilla, by default, provides the minecraft:default test environment which does not do anything. However, additional test environments can be created using the available test definition types.
Game Rules
This environment type sets the game rules to use for the test. During teardown, the game rules are set back to their default value.
// examplemod:example_environment
// In 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:game_rules",
// A list of game rules with boolean values to set
"bool_rules": [
{
// The name of the rule
"rule": "doFireTick",
"value": false
}
// ...
],
// A list of game rules with integer values to set
"int_rules": [
{
"rule": "playersSleepingPercentage",
"value": 50
}
// ...
]
}
Time of Day
This environment type sets the time to some non-negative integer, similar to how the /time set <number> command is used.
// examplemod:example_environment
// In 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:time_of_day",
// Sets the time of day in the world
// Common values:
// - Day -> 1000
// - Noon -> 6000
// - Night -> 13000
// - Midnight -> 18000
"time": 13000
}
Weather
This environment type sets the weather, similar to how the /weather command is used.
// examplemod:example_environment
// In 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:weather",
// Can be one of three values:
// - clear (No weather)
// - rain (Rain)
// - thunder (Rain and thunder)
"weather": "thunder"
}
Function
This environment type provides two ResourceLocations to mcfunctions to setup and teardown the level, respectively.
// examplemod:example_environment
// In 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:function",
// The setup mcfunction to use
// If not specified, nothing will be ran
// Points to 'data/examplemod/function/example/setup.mcfunction'
"setup": "examplemod:example/setup",
// The teardown mcfunction to use
// If not specified, nothing will be ran
// Points to 'data/examplemod/function/example/teardown.mcfunction'
"teardown": "examplemod:example/teardown"
}
Composite
If multiple combinations are required, then the composite environment type (aptly named all_of) can be used to string multiple of the above environment types together.
// examplemod:example_environment
// In 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:all_of",
// A list of test environments to use
// Can either specified the registry name or the environment itself
"definitions": [
// Points to 'data/minecraft/test_environment/default.json'
"minecraft:default",
{
// A raw environment definition
"type": "..."
}
// ...
]
}
Custom Types
If none of the types above work, then a custom definition can be created by implementing TestEnvironmentDefinition and creating an associated MapCodec:
public record ExampleEnvironmentType(int value1, boolean value2) implements TestEnvironmentDefinition {
// Construct the map codec to register
public static final MapCodec<ExampleEnvironmentType> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.INT.fieldOf("value1").forGetter(ExampleEnvironmentType::value1),
Codec.BOOL.fieldOf("value2").forGetter(ExampleEnvironmentType::value2)
).apply(instance, ExampleEnvironmentType::new)
);
@Override
public void setup(ServerLevel level) {
// Setup whatever is necessary here
}
@Override
public void teardown(ServerLevel level) {
// Undo whatever was changed within the setup method
// This should either return to default or the previous value
}
@Override
public MapCodec<ExampleEnvironmentType> codec() {
return CODEC;
}
}
Then register the MapCodec using whatever registry method is required by your mod loader:
Registry.register(
BuiltInRegistries.TEST_ENVIRONMENT_DEFINITION_TYPE,
ResourceLocation.fromNamespaceAndPath("examplemod", "example_environment_type"),
ExampleEnvironmentType.CODEC
);
Finally, you can use it in your environment definition:
// examplemod:example_environment
// In 'data/examplemod/test_environment/example_environment.json'
{
"type": "examplemod:example_environment_type",
"value1": 0,
"value2": true
}
Test Functions
The initial concept of game tests were structured around running functions from GameTestHelper determining whether the test succeeds or fails. Test functions are the registry-driven representation of those. Essentially, every test function is a method that takes in a GameTestHelper.
At the moment, vanilla only provides minecraft:always_pass, which just calls GameTestHelper#succeed. Test functions are also not generated, meaning it simply runs the value with whatever is provided. As such, a test function should generally represent a single old game test:
Registry.register(
BuiltInRegistries.TEST_FUNCTION,
ResourceLocation.fromNamespaceAndPath("examplemod", "example_function"),
(GameTestHelper helper) -> {
// Run whatever game test commands you want
helper.assertBlockPresent(...);
// Make sure you have some way to succeed
helper.succeedIf(() -> ...);
}
);
Test Data
Now that we have environments and test functions, we can get into defining our game test. This is done through TestData, which is the equivalent of the GameTest annotation. The only things changed are that structures are now referenced by their ResourceLocation via structure, GameTest#timeoutTicks is now renamed to TestData#maxTicks, and instead of specifying GameTest#rotationSteps, you simply provide the Rotation via TestData#rotation. Everything else remains the same, just represented in a different format.
The Game Test Instance
With the TestData in hand, we can now link everything together through the GameTestInstance. This instance is what actually represents a single test. Once again, vanilla only provides the default minecraft:always_pass, so we will need to construct the instance ourselves.
The Original Instance
The previous game tests are implemented using minecraft:function, which links a test function to the test data.
// examplemod:example_test
// In 'data/examplemod/test_instance/example_test.json'
{
"type": "minecraft:function",
// Points to a 'Consumer<GameTestHelper>' in the test function registry
"function": "examplemod:example_function",
// The 'TestData' information
// The environment to run the test in
// Points to 'data/examplemod/test_environment/example_environment.json'
"environment": "examplemod:example_environment",
// The structure used for the game test
// Points to 'data/examplemod/structure/example_structure.nbt'
"structure": "examplemod:example_structure",
// The number of ticks that the game test will run until it automatically fails
"max_ticks": 400,
// The number of ticks that are used to setup everying required for the game test
// This is not counted towards the maximum number of ticks the test can take
// If not specified, defaults to 0
"setup_ticks": 50,
// Whether the test is required to succeed to mark the batch run as successful
// If not specified, defaults to true
"required": true,
// Specifies how the structure and all subsequent helper methods should be rotated for the test
// If not specified, nothing is rotated
"rotation": "clockwise_90",
// When true, the test can only be ran through the `/test` command
// If not specified, defaults to false
"manual_only": true,
// Specifies the maximum number of times that the test can be reran
// If not specified, defaults to 1
"max_attempts": 3,
// Specifies the minimum number of successes that must occur for a test to be marked as successful
// This must be less than or equal to the maximum number of attempts allowed
// If not specified, defaults to 1
"required_successes": 1,
// Returns whether the structure boundary should keep the top empty
// This is currently only used in block-based test instances
// If not specified, defaults to false
"sky_access": false
}
Block-Based Instances
Vanilla also provides a block-based test instance via minecraft:block_based. This is handled through via structures with test blocks receiving signals via Level#hasNeighborSignal. To start, a structure must have one test block which is set to its start mode. This block is then triggered, sending a fifteen signal pulse for one tick. Structures may then have as many test blocks with either a log, accept, or fail mode set. Log test blocks also send a fifteen signal pulse when activated. Accept and fail test blocks either succeed or fail the game test if any of them are activated (success takes precedent over failure).
As this test relies on test blocks in the structure, no additional information is required other than the test data:
// examplemod:example_test
// In 'data/examplemod/test_instance/example_test.json'
{
"type": "minecraft:block_based",
// The 'TestData' information
// Points to 'data/examplemod/test_environment/example_environment.json'
"environment": "examplemod:example_environment",
// Points to 'data/examplemod/structure/example_structure.nbt'
"structure": "examplemod:example_structure",
"max_ticks": 400,
"setup_ticks": 50,
"required": true,
"rotation": "clockwise_90",
"manual_only": true,
"max_attempts": 3,
"required_successes": 1,
"sky_access": false
}
Custom Tests
If you need to implement your own test-based logic, whether using a more dynamic feature or because you can't be bothered to migrated all of your data logic to the new systems, you can create your own custom test instance by extending GameTestInstance and creating an associated MapCodec:
public class ExampleTestInstance extends GameTestInstance {
// Construct the map codec to register
public static final MapCodec<ExampleTestInstance> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.INT.fieldOf("value1").forGetter(test -> test.value1),
Codec.BOOL.fieldOf("value2").forGetter(test -> test.value2),
TestData.CODEC.forGetter(ExampleTestInstance::info)
).apply(instance, ExampleTestInstance::new)
);
public ExampleTestInstance(int value1, boolean value2, TestData<Holder<TestEnvironmentDefinition>> info) {
super(info);
}
@Override
public void run(GameTestHelper helper) {
// Run whatever game test commands you want
helper.assertBlockPresent(...);
// Make sure you have some way to succeed
helper.succeedIf(() -> ...);
}
@Override
public MapCodec<ExampleTestInstance> codec() {
return CODEC;
}
@Override
protected MutableComponent typeDescription() {
// Provides a description about what this test is supposed to be
// Should use a translatable component
return Component.literal("Example Test Instance");
}
}
Then register the MapCodec using whatever registry method is required by your mod loader:
Registry.register(
BuiltInRegistries.TEST_INSTANCE_TYPE,
ResourceLocation.fromNamespaceAndPath("examplemod", "example_test_instance"),
ExampleTestInstance.CODEC
);
Finally, you can use it in your test instance:
// examplemod:example_test
// In 'data/examplemod/test_instance/example_test.json'
{
"type": "examplemod:example_test_instance",
"value1": 0,
"value2": true,
// The 'TestData' information
// Points to 'data/examplemod/test_environment/example_environment.json'
"environment": "examplemod:example_environment",
// Points to 'data/examplemod/structure/example_structure.nbt'
"structure": "examplemod:example_structure",
"max_ticks": 400,
"setup_ticks": 50,
"required": true,
"rotation": "clockwise_90",
"manual_only": true,
"max_attempts": 3,
"required_successes": 1,
"sky_access": false
}
net.minecraft.client.renderer.blockentityBeaconRenderernow has a generic that takes in a subtype ofBlockEntityandBeaconBeamOwnerStructureBlockRenderer->BlockEntityWithBoundingBoxRenderer, not one-to-one
net.minecraft.core.registries.Registries#TEST_FUNCTION,TEST_ENVIRONMENT_DEFINITION_TYPE,TEST_INSTANCE_TYPEnet.minecraft.gametest.Main- The entrypoint for the game test server.net.minecraft.gametest.frameworkAfterBatch,BeforeBatchannotations are removedBlockBasedTestInstance- A test instance for testing the test block.BuiltinTestFunctions- Contains all registered test functions.FailedTestTracker- An object for holding all game tests that failed.FunctionGameTestInstance- A test instance for running a test function.GameTestannotation is removedGameTestAssertExceptionnow extendsGameTestExceptionGameTestException- An exception thrown during the execution of a game test.GameTestBatchnow takes in an index and environment definition instead of a name and batch setupsGameTestBatchFactoryfromTestFunction->divideIntoBatches, not one-to-onetoGameTestInfois removedtoGameTestBatchnow takes in an environment definition and an index$TestDecorator- Creates a list of test infos from a test instance and level.
GameTestEnvironments- Contains all environments used for batching game test instances.GameTestGeneratorannotation is removedGameTestHelpertickBlock- Ticks the block at the specific position.assertionException- Returns a new exception to throw on error.getBlockEntitynow takes in aClassto cast the block entity toassertBlockTag- Checks whether the block at the position is within the provided tag.assertBlocknow takes in a block -> component function for the error message.assertBlockPropertynow takes in aComponentinstead of a stringassertBlockStatenow takes in either nothing, a blockstate -> component function, or a supplied componentassertRedstoneSignalnow takes in a supplied componentassertContainerSingle- Asserts that a container contains exactly one of the item specified.assertEntityPosition,assertEntityPropertynow takes in a componentfailnow takes in aComponentfor the error messageassertTrue,assertValueEqual,assertFalsenow takes in a component
GameTestInfonow takes in a holder-wrappedGameTestInstanceinstead of aTestFunctionsetStructureBlockPos->setTestBlockPosplaceStructurenow returns nothinggetTestName-id, not one-to-onegetStructureBlockPos->getTestBlockPosgetStructureBlockEntity->getTestInstanceBlockEntitygetStructureName->getStructuregetTestFunction->getTest,getTestHolder, not one-to-onegetOrCalculateNorthwestCorner,setNorthwestCornerare removedfailnow takes in aComponentorGameTestExceptioninstead of aThrowablegetErrornow returns aGameTestExceptioninstead of aThrowable
GameTestInstance- Defines a test to run.GameTestInstances- Contains all registered tests.GameTestMainUtil- A utility for running the game test server.GameTestRegistryclass is removedGameTestSequencetickAndContinue,tickAndFailIfNotCompletenow take in an integer for the tick instead of a longthenFailnow takes in a suppliedGameTestExceptioninstead of aThrowable
GameTestServer#createnow takes in an optional string and boolean instead of the collection of test functions and the starting positionGeneratedTest- A object holding the test to run for the given environment and the function to applyGameTestTicker$State- An enum containing what state the game test ticker is currently executing.GameTestTimeoutExceptionnow extendsGameTestExceptionReportGameListener#spawnBeaconis removedStructureBlockPosFinder->TestPosFinderStructureUtilstestStructuresDiris now a pathgetStructureBounds,getStructureBoundingBox,getStructureOrigin,addCommandBlockAndButtonToStartTestare removedcreateNewEmptyStructureBlock->createNewEmptyTest, not one-to-onegetStartCorner,prepareTestStructure,encaseStructure,removeBarriersare removedfindStructureBlockContainingPos->findTestContainingPosfindNearestStructureBlock->findNearestTestfindStructureByTestFunction,createStructureBlockare removedfindStructureBlocks->findTestBlockslookedAtStructureBlockPos->lookedAtTestPos
TestClassNameArgumentis removedTestEnvironmentDefinition- Defines the environment that the test is run on by setting the data on the level appropriately.TestFinderno longer contains a generic for the context$Builder#allTests,allTestsInClass,locateByNameare removed$Builder#byArgument->byResourceSelection
TestFunction->TestData, not one-to-oneTestFunctionArgument->net.minecraft.commands.arguments.ResourceSelectorArgumentTestFunctionFinder->TestInstanceFinderTestFunctionLoader- Holds the list of test functions to load and run.UnknownGameTestException- An exception that is thrown when the error of the game test is unknown.
net.minecraft.network.protocol.gameClientboundTestInstanceBlockState- A packet sent to the client containing the status of a test along with its size.ServerboundSetTestBlockPacket- A packet sent to the server to set the information within the test block to run.ServerboundTestInstanceBlockActionPacket- A packet sent to the server to set up the test instance within the test block.
net.minecraft.world.entity.player.PlayeropenTestBlock- Opens a test block.openTestInstanceBlock- Opens a test block for a game test instance.
net.minecraft.world.level.blockTestBlock- A block used for running game tests.TestInstanceBlock- A block used for managing a single game test.
net.minecraft.world.level.block.entityBeaconBeamOwner- An interface that represents a block entity with a beacon beam.BeaconBlockEntitynow implementsBeaconBeamOwnerBeaconBeamSection->BeaconBeamOwner$Section
BoundingBoxRenderable- An interface that represents a block entity that can render an arbitrarily-sized bounding box.StructureBlockEntitynow implementsBoundingBoxRenderableTestBlockEntity- A block entity used for running game tests.TestInstanceBlockEntity- A block entity used for managing a single game test.
net.minecraft.world.level.block.state.properties.TestBlockMode- A property for representing the current state of the game tests associated with a test block.
Data Component Getters
The data component system can now be represented on arbitrary objects through the use of the DataComponentGetter. As the name implies, the getter is responsible for getting the component from the associated type key. Both block entities and entities use the DataComponentGetter to allow querying the internal data, such as variant information or custom names. They both also have methods for collecting the data components from another holder (via applyImplicitComponents or applyImplicitComponent). Block entities also contain a method for collection to another holder via collectImplicitComponents.
Items
ItemSubPredicates have been completely replaced with DataComponentPredicates. Each sub predicate has its appropriate analog within the system.
net.minecraft.advancements.critereon.*->net.minecraft.core.component.predicates.*ItemAttributeModifiersPredicate->AttributeModifiersPredicateItemBundlePredicate->BundlePredicateItemContainerPredicate->ContainerPredicateItemCustomDataPredicate->CustomDataPredicateItemDamagePredicate->DamagePredicateItemEnchantmentsPredicate->EnchantmentsPredicateItemFireworkExplosionPredicate->FireworkExplosionPredicateItemFireworksPredicate->FireworksPredicateItemJukeboxPlayablePredicate->JukeboxPlayablePredicateItemPotionsPredicate->PotionsPredicateItemSubPredicate->DataComponentPredicate, not one-to-oneSINGLE_STREAM_CODEC
ItemSubPredicates->DataComponentPredicates, not one-to-oneItemTrimPredicate->TrimPredicateItemWritableBookPredicate->WritableBookPredicateItemWrittenBookPredicate->WrittenBookPredicate
net.minecraft.advancements.critereonBlockPredicatenow takes in aDataComponentMatchersfor matching any delegated component dataDataComponentMatchers- A predicate that operates on aDataComponentGetter, matching any exact and partial component data on the provider.EntityPredicatenow takes in aDataComponentMatchersinstead of aOptional<DataComponentExactPredicate>ItemPredicatenow takes in aDataComponentMatchersfor matching any delegated component dataNbtPredicate#matchesnow takes in aDataComponentGetterinstead of anItemStackSingleComponentItemPredicatenow implementsDataComponentPredicateinstead ofItemSubPredicatematches(ItemStack, T)->matches(T)
net.minecraft.core.componentDataComponentPatchDELIMITED_STREAM_CODEC$CodecGetter- Gets the codec for a given component type.
DataComponentPredicate->DataComponentExactPredicateisEmpty- Checks if the expected components list within the predicate is empty.
net.minecraft.core.registries.Registries#ITEM_SUB_PREDICATE_TYPE->DATA_COMPONENT_PREDICATE_TYPE, not one-to-onenet.minecraft.world.item.AdventureModePredicateno longer takes in a boolean to show in tooltipnet.minecraft.world.itemBannerItem#appendHoverTextFromBannerBlockEntityTagis removedItem#appendHoverText(ItemStack, Item.TooltipContext, List<Component>, TooltipFlag)->appendHoverText(ItemStack, Item.TooltipContext, TooltipDisplay, Consumer<Component>, TooltipFlag), now deprecatedItemStackaddToTooltipis now publicaddDetailsToTooltip- Appends the component details of an item to the tooltip.
JukeboxPlayable#showInTooltipis removed
net.minecraft.world.item.componentBlockItemStatePropertiesnow implementsTooltipProviderChargedProjectilesnow implementsTooltipProviderCustomData#itemMatcheris removedDyedItemColor#showInTooltipis removedFireworkExplosion#addShapeNameTooltipis removedItemAttributeModifiers#showInTooltipis removedItemContainerContentsnow implementsTooltipProviderSeededContainerLootnow implementsTooltipProviderTooltipDisplay- A component that handles what should be hidden within an item's tooltip.TooltipProvider#addToTooltipnow takes in aDataComponentGetter
net.minecraft.world.item.enchantment.ItemEnchantments#showInTooltipis removednet.minecraft.world.item.equipment.trim.ArmorTrim#showInTooltipis removednet.minecraft.world.item.trading.ItemCostnow takes in aDataComponentExactPredicateinstead of aDataComponentPredicatenet.minecraft.world.level.block.Block#appendHoverTextis removednet.minecraft.world.level.block.entityBannerPatternLayersnow implementsTooltipProviderPotDecorationsnow implementsTooltipProvider
net.minecraft.world.level.saveddata.maps.MapIdnow implementsTooltipProvider
Entities
Some EntitySubPredicates for entity variants have been transformed into data components stored on the held item due to a recent change on EntityPredicate now taking in a DataComponentExactPredicate for matching the slots on an entity.
net.minecraft.advancements.critereonEntityPredicatenow takes in aDataComponentExactPredicateto match the equipment slots checkedEntitySubPredicateAXOLTOL->DataComponents#AXOLOTL_VARIANTFOX->DataComponents#FOX_VARIANTMOOSHROOM->DataComponents#MOOSHROOM_VARIANTRABBIT->DataComponents#RABBIT_VARIANTHORSE->DataComponents#HORSE_VARIANTLLAMA->DataComponents#LLAMA_VARIANTVILLAGER->DataComponents#VILLAGER_VARIANTPARROT->DataComponents#PARROT_VARIANTSALMON->DataComponents#SALMON_SIZETROPICAL_FISH->DataComponents#TROPICAL_FISH_PATTERN,TROPICAL_FISH_BASE_COLOR,TROPICAL_FISH_PATTERN_COLORPAINTING->DataComponents#PAINTING_VARIANTCAT->DataComponents#CAT_VARIANT,CAT_COLLARFROG->DataComponents#FROG_VARIANTWOLF->DataComponents#WOLF_VARIANT,WOLF_COLLARPIG->DataComponents#PIG_VARIANTregisterwith variant subpredicates have been removedcatVariant,frogVariant,wolfVariantare removed$EntityHolderVariantPredicateType,$EntityVariantPredicateTypeare removed
SheepPredicateno longer takes in theDyeColor
net.minecraft.client.renderer.entity.state.TropicalFishRenderState#variant->patternnet.minecraft.core.componentDataComponentGetter- A getter that obtains data components from some object.DataComponentHolder,DataComponentMapnow extendsDataComponentGetterDataComponentExactPredicateis now a predicate of aDataComponentGetterexpect- A predicate that expects a certain value for a data component.test(DataComponentHolder)is removed
DataComponentsSHEEP_COLOR- The dye color of a sheep.SHULKER_COLOR- The dye color of a shulker (box).COW_VARIANT- The variant of a cow.CHICKEN_VARIANT- The variant of a chicken.WOLF_SOUND_VARIANT- The sounds played by a wolf.
net.minecraft.world.entityEntitynow implementsDataComponentGetterapplyImplicitComponents- Applies the components from the getter onto the entity. This should be overriden by the modder.applyComponentsFromItemStack- Applies the components from the stack onto the entity.castComponentValue- Casts the type of the object to the component type.setComponent- Sets the component data onto the entity.applyImplicitComponent- Applies the component data to the entity. This should be overriden by the modder.applyImplicitComponentIfPresent- Applies the component if it is present on the getter.
EntityType#appendCustomNameConfig->appendComponentsConfigVariantHolderinterface is removed- As such, all
setVariantmethods on relevant entities are private while the associated data can also be obtained from theDataComponentGetter
- As such, all
net.minecraft.world.entity.animalCatVariant#CODECFox$Variant#STREAM_CODECFrogVariant#CODECMushroomCow$Variant#STREAM_CODECParrot$Variant#STREAM_CODECRabbit$Variant#STREAM_CODECSalmon$Variant#STREAM_CODECTropicalFishgetVariant->getPattern$Patternnow implementsTooltipProvider
Wolf->.wolf.WolfWolfVariant->.wolf.WolfVariant, now a record, taking in an$AssetInfoand aSpawnPrioritySelectorsWolfVariants->.wolf.WolfVariants
net.minecraft.world.entity.animal.axolotl.Axolotl$Variant#STREAM_CODECnet.minecraft.world.entity.animal.horseLlama$Variant#STREAM_CODECVariant#STREAM_CODEC
net.minecraft.world.entity.animal.wolfWolfSoundVariant- The sounds played by a wolf.WolfSoundVariants- All vanilla wolf sound variants.
net.minecraft.world.entity.decoration.PaintingVARIANT_MAP_CODECis removedVARIANT_CODECis now private
net.minecraft.world.entity.npc.VillagerDataHolder#getVariant,setVariantare removednet.minecraft.world.entity.variant.VariantUtils- A utility for getting the variant info of an entity.net.minecraft.world.itemItemStack#copyFrom- Copies the component from the getter.MobBucketItem#VARIANT_FIELD_CODEC->TropicalFish$Pattern#STREAM_CODEC
net.minecraft.world.level.block.entity.BlockEntity#applyImplicitComponentsnow takes in aDataComponentGetter$DataComponentInput->DataComponentGetter
net.minecraft.world.level.Spawnermethods now takes in aCustomDatainstead of theItemStackitself
Spawn Conditions
To allow entities to spawn variants randomly but within given conditions, a new registry called SPAWN_CONDITION_TYPE was added. These take in SpawnConditions: a selector that acts like a predicate to take in the context to see whether the given variant can spawn there. All of the variants are thrown into a list and then ordered based on the selected priorty stored in the SpawnProritySelectors. Those with a higher priority will be checked first, with multiple of the same priority selected in the order they are provided. Then, all variants on the same priority level where a condition has been met is selected at random.
// For some object where there are spawn conditions
[
{
// The spawn condition being checked
"condition": {
"type": "minecraft:biome",
// Will check that the biome the variant is attempting to spawn in is in the forest
"biomes": "#minecraft:is_forest"
},
// Will check this condition first
"priority": 1
},
{
// States that the condition will always be true
"priority": 0
}
]
net.minecraft.core.registries.Registries#SPAWN_CONDITION_TYPEnet.minecraft.world.entity.variantBiomeCheck- A spawn condition that checks whether the entity is in one of the given biomes.MoonBrightnessCheck- A spawn condition that checks the brightness of the moon.PriorityProvider- An interface which orders the condition selectors based on some priority integer.SpawnCondition- Checks whether an entity can spawn at this location.SpawnConditions- The available spawn conditions to choose from.SpawnContext- An object holding the current position, level, and biome the entity is being spawned within.SpawnPrioritySelectors- A list of spawn conditions to check against the entity. Used to select a random variant to spawn in a given location.StructureCheck- A spawn condition that checks whether the entity is within a structure.
Variant Datapack Registries
Frog, cat, cow, chicken, pig, and wolf, and wolf sound variants are datapack registry objects, meaning that most references now need to be referred to through the RegistryAccess or HolderLookup$Provider instance.
For a frog, cat, or wolf:
// A file located at:
// - `data/examplemod/frog_variant/example_frog.json`
// - `data/examplemod/cat_variant/example_cat.json`
// - `data/examplemod/wolf_variant/example_wolf.json`
{
// Points to a texture at `assets/examplemod/textures/entity/cat/example_cat.png`
"asset_id": "examplemod:entity/cat/example_cat",
"spawn_conditions": [
// The conditions for this variant to spawn
{
"priority": 0
}
]
}
For a pig, cow, or chicken:
// A file located at:
// - `data/examplemod/pig_variant/example_pig.json`
// - `data/examplemod/cow_variant/example_cow.json`
// - `data/examplemod/chicken_variant/example_chicken.json`
{
// Points to a texture at `assets/examplemod/textures/entity/pig/example_pig.png`
"asset_id": "examplemod:entity/pig/example_pig",
// Defines the `PigVariant$ModelType` that's used to select what entity model to render the pig variant with
"model": "cold",
"spawn_conditions": [
// The conditions for this variant to spawn
{
"priority": 0
}
]
}
For a wolf sound variant:
// A file located at:
// - `data/examplemod/wolf_sound_variant/example_wolf_sound.json``
{
// The registry name of the sound event to play randomly on idle
"ambient_sound": "minecraft:entity.wolf.ambient",
// The registry name of the sound event to play when killed
"death_sound": "minecraft:entity.wolf.death",
// The registry name of the sound event to play randomly when angry on idle
"growl_sound": "minecraft:entity.wolf.growl",
// The registry name of the sound event to play when hurt
"hurt_sound": "minecraft:entity.wolf.hurt",
// The registry name of the sound event to play randomly
// 1/3 of the time on idle when health is max
"pant_sound": "minecraft:entity.wolf.pant",
// The registry name of the sound event to play randomly
// 1/3 of the time on idle when health is below max
"whine_sound": "minecraft:entity.wolf.whine"
}
Client Assets
Raw ResourceLocations within client-facing files for identifiers or textures are being replaced with objects defining an idenfitier along with a potential texture path. There are three main objects to be aware of: ClientAsset, ModelAndTexture, and MaterialAssetGroup.
ClientAsset is an id/texture pair used to point to a texture location. By default, the texture path is contructed from the id, with the path prefixed with textures and suffixed with the PNG extension.
ModelAndTexture is a object/client asset pair used when a renderer should select between multiple models. Usually, the renderer creates a map of the object type to the model, and the object provided to the ModelAndTexture is used as a lookup into the map.
MaterialAssetGroup is a handler for rendering an equipment asset with some trim material. It takes in the base texture used to overlay onto the armor along with any overrides for a given equipment asset.
net.minecraft.advancements.DisplayInfonow takes in aClientAssetinstead of only aResourceLocationfor the background texturenet.minecraft.client.modelAdultAndBabyModelPair- Holds twoModelinstances that represents the adult and baby of some entity.ChickenModel#createBaseChickenModel- Creates the default chicken model.ColdChickenModel- A variant model for a chicken in cold temperatures.ColdCowModel- A variant model for a cow in cold temperatures.ColdPigModel- A variant model for a big in cold temperatures.CowModel#createBaseCowModel- Creates the base model for a cow.PigModel#createBasePigModel- Creates the default pig model.WarmCowModel- A variant model for a cow in warm temperatures.
net.minecraft.client.renderer.entityChickenRenderernow extendsMobRendererinstead ofAgeableMobRendererCowRenderernow extendsMobRendererinstead ofAgeableMobRendererPigRenderernow extendsMobRendererinstead ofAgeableMobRenderer
net.minecraft.client.renderer.entity.layers.SheepWoolUndercoatLayer- A layer that renders the wool undercoat of a sheep.net.minecraft.client.renderer.entity.stateCowRenderState- A render state for a cow entity.SheepRenderStategetWoolColor- Returns the integer color of the sheep wool.isJebSheep- Returns whether the sheep's name contains thejeb_prefix.
net.minecraft.core.ClientAsset- An object that holds an identifier and a path to some texture.net.minecraft.data.loot.EntityLootSubProvider#killedByFrogVariantnow takes in aHolderGetterfor theFrogVariantnet.minecraft.data.tags.CatVariantTagsProviderclass is removednet.minecraft.tags.CatVariantTagsclass is removednet.minecraft.world.entity.animalAbstractCow- An abstract animal that represents a cow.Chicken#setVariant,getVariant- Handles the variant information of the chicken.ChickenVariant- A class which defines the common-sideable rendering information and biome spawns of a given chicken.ChickenVariants- Holds the keys for all vanilla chicken variants.Cownow extendsAbstractCow.CowVariant- A class which defines the common-sideable rendering information and biome spawns of a given cow.CowVariants- Holds the keys for all vanilla cow variants.CatVariant(ResourceLocation)->CatVariant(ClientAsset, SpawnPrioritySelectors)CatVariants- Holds the keys for all vanilla cat variants.FrogVariant->.frog.FrogVariantFrogVariant(ResourceLocation)->FrogVariant(ClientAsset, SpawnPrioritySelectors)
MushroomCownow extendsAbstractCowPigVariant- A class which defines the common-sideable rendering information and biome spawns of a given pig.TemperatureVariants- An interface which holds theResourceLocations that indicate an entity within a different temperature.
net.minecraft.world.entity.variant.ModelAndTexture- Defines a model with its associated texture.net.minecraft.world.item.equipment.trimMaterialAssetGroup- An asset defines some base and the permutations based on the equipment worn.TrimMaterialnow takes in aMaterialAssetGroupinstead of the raw base and overrides
Tags and Parsing
Tags have received a rewrite, removing any direct references to types while also sealing and finalizing related classes. Getting a value from the tag now returns an Optional-wrapped entry, unless you call one of the get*Or, where you specify the default value. Objects, on the other hand, do not take in a default, instead returning an empty variant of the desired tag.
// For some `CompoundTag` tag
// Read a value
Optional<Integer> value1 = tag.getInt("value1");
int value1Raw = tag.getIntOr("value1", 0);
// Reading another object
Optional<CompoundTag> childTag = tag.getCompound("childTag");
CompoundTag childTagRaw = tag.getCopmoundOrEmpty("childTag");
Writing with Codecs
CompoundTags now have methods to write and read using a Codec or MapCodec. For a Codec, it will store the serialized data inside the key specified. For a MapCodec, it will merge the fields onto the top level tag.
// For some Codec<ExampleObject> CODEC and MapCodec<ExampleObject> MAP_CODEC
// We will also have ExampleObject example
CompoundTag tag = new CompoundTag();
// For a codec
tag.store("example_key", CODEC, example);
Optional<ExampleObject> fromCodec = tag.read("example_key", CODEC);
// For a map codec
tag.store(MAP_CODEC, example);
Optional<ExampleObject> fromMapCodec = tag.read(MAP_CODEC);
Command Parsers
The packrat parser has been updated with new rules and systems, allowing commands to have parser-based arguments. This comes from the CommandArgumentParser, which parses some grammar to return the desired object. The parser is then consumed by the ParserBasedArgument, where it attempts to parse a string and build any suggestions based on what you're currently typing. These are both handled through the Grammar class, which implements CommandArgumentParser, constructed using a combination of atoms, dictionaries, rules, and terms.
net.minecraft.commands.ParserUtils#parseJsonnet.minecraft.commands.argumentsComponentArgumentnow extendsParserBasedArgumentNbtTagArgumentnow extendsParserBasedArgumentStyleArgumentnow extendsParserBasedArgument
net.minecraft.commands.arguments.item.ItemPredicateArgumentnow extendsParserBasedArgumentnet.minecraft.nbtByteArrayTag, now final, no longer takes in a list objectByteTagis now a recordCollectionTagis now a sealed interface, no longer extendingAbstractListor has a genericset,addis removedremovenow returns aTagget- Returns the tag at the specified index.getElementTypeis removedsize- Returns the size of the collection.isEmpty- Returns whether the collection has no elements.stream- Streams the elements of the collection.
CompoundTagis now finalstore- Writes a codec or map codec to the tag.read- Reads the codec or map codec-encoded value from the tag.getFloatOrDefault,getIntOrDefault,getLongOrDefault- Gets the value with the associated key, or the default if not present or an exception is thrown.storeNullable- When not null, uses the codec to write the value to the tag.putUUID,getUUID,hasUUIDis removedgetAllKeys->keySetvalues,forEach- Implements the standard map operations.putByteArray,putIntArraywith list objects are removedgetTagTypeis removedcontainsis removedget*,get*Or- Returns an optional wrapped object for the key, or the default value specified is using theOrmethods.
DoubleTagis now a recordEndTagis now a recordFloatTagis now a recordIntArrayTag, now final, no longer takes in a list objectIntTagis now a recordListTag, now final, extendsAbstractListaddAndUnwrap- Adds the tag to the list where, if a compound with one element, adds the inner tag instead.get*,get*Or- Returns an optional wrapped object for the key, or the default value specified is using theOrmethods.compoundStream- Returns a flat map of allCompoundTags within the list.
LongArrayTag, now final, no longer takes in a list objectLongTagis now a recordNbtIo#readUnnamedTagis now public, visible for testingNbtOpsnow has a private constructorNbtUtilsgetDataVersionnow has an overload that takes in aDynamiccreateUUID,loadUUIDis removedreadBlockPos,writeBlockPosis removed
NumericTagis now a sealed interface that implementsPrimitiveTaggetAsLong->longValuegetAsInt->intValuegetAsShort->shortValuegetAsByte->byteValuegetAsDouble->doubleValuegetAsFloat->floatValuegetAsNumber->boxas*- Returns an optional wrapped of the numeric value.
PrimitiveTag- A sealed interface that represents the tag data as being a primitive object.ShortTagis now a recordSnbtGrammar- A parser creater for stringified NBTs.SnbtOperations- A helper that contains the built in operations for parsing some value.StringTagis now a recordStringTagVisitorvisit->build, not one-to-onehandleEscape->handleKeyEscape, now private
Tagis now a sealed interfaceas*-> Attempts to cast the tag as one of its subtypes, returning an empty optional on failure.getAsString->asString, not one-to-one
TagParsernow holds a generic referncing the type of the intermediate object to parse to- The constructor now takes in a grammar, or
createconstructs the grammar from aDynamicOps AS_CODEC->FLATTENED_CODECparseTag->parseCompoundFullyorparseCompoundAsArgument- Additional methods such as
parseFully,parseAsArgumentparse to some intermediary object - These are all instance methods
- Additional methods such as
readKey,readTypedValueis removed
- The constructor now takes in a grammar, or
TagType#isValueis removed
net.minecraft.util.parsing.packratCachedParseState- A parse state that caches the parsed positions and controls when reading.Control#hasCut- Returns whether the control flow for the grammar has a cut for the reading object.DelayedException- An interface that creates an exception to throw.Dictionaryputnow returns aNamedRuleput(Atom<T>, Term<S>, Rule.RuleAction<S, T>)->putComplexget->getOtThrow, not one-to-oneforward- Gets or writes the term to the dictionary.namedWithAlias- Creates a new reference to the named atom or its alias.
ErrorCollector$Nop- A error collector that does nothing.NamedRule- A rule that has an associated name.ParseStateis now an interface- Caching logic has moved to
CachedParseState scope- Returns the current scope being analyzed within the parsing object.parsenow takes in aNamedRuleinstead of anAtomacquireControl,releaseControl- Handles obtaining theControlused during parsing.silent- Returns aParseStatethat does not collect any errors.
- Caching logic has moved to
Ruleparse,$RuleAction#runnow returns a nullable value rather than an optionalSimpleRuleActionnow implements$RuleAction
Scope#pushFrame,popFrame,splitFrame,clearFrameValues,mergeFrame- Handles the management of parsing terms into sections called frames.Termnamed->Dictionary#named, not one-to-onerepeated,repeatedWithTrailingSeparator,repeatedWithoutTrailingSeparator- Handles terms similar to varargs that are repeated and sticks them into a list.positiveLookahead,negativeLookahead- Handles a term that matches information based on what is following.fail- Mark a term as having failed during parsing.
net.minecraft.util.parsing.packrat.commandsCommandArgumentParser- Parses a string into an argument for use with a command.Grammarnow takes in aNamedRulefor the top rather than anAtomGreedyPatternParseRule- A rule that attempts to match the provided pattern greedily, assuming that if a region matches, that the matched group can be obtained.GreedyPredicateParseRule- A rule that attempts to match the accepted characters greedily, making sure that the string reaches a minimum size.NumberRunParseRule- A rule that attempts to parse a number from the string.ParserBasedArgument- A command argument that uses a parser to extract the value.ResourceLookupRulenow takes in aNamedRulefor the id parser rather than anAtomStringReaderParserStatenow extendsCachedParsedState- The
Dictoionaryis no longer taken in
- The
StringReaderTerms#characters- Matches multiple characters in a string, usually for catching both the lowercase and uppercase variant.UnquotedStringParseRule- A rule that reads part of the sequence as an unquoted string, making sure it reaches a minimum size.
Saved Data, now with Types
SavedData has been reworked to abstract most of its save and loading logic into a separate SavedDataType. This means that the save override and additional load and factory methods are now handled within the SavedDataType itself.
To construct a SavedDataType, you need to pass in four paramters. First is the string identifier, used to resolve the .dat file holding your information. This must be a vaild path. Then there is the constructor, which takes in the SavedData$Context to return an instance of your data object when no information is present. Following that is the codec, which takes in the SavedData$Context and returns a Codec to read and write your saved data. Finally, there is the DataFixTypes used for data fixers. As this is a static enum, you will either need to inject into the enum itself, if you plan on using vanilla data fixers, or patch out the update call within DimensionDataStorage#readTagFromDisk to pass in a null value.
// Our saved data instance
public class ExampleSavedData extends SavedData {
// The saved data type
public static final SavedDataType<ExampleSavedData> TYPE = new SavedDataType<>(
// Best to preface the identifier with your mod id followed by an underscore
// Slashes will throw an error as the folders are not present
// Will resolve to `saves/<world_name>/data/examplemod_example.dat`
"examplemod_example",
// Constructor for the new instance
ExampleSavedData::new,
// Codec factory to encode and decode the data
ctx -> RecordCodecBuilder.create(instance -> instance.group(
RecordCodecBuilder.point(ctx.levelOrThrow()),
Codec.INT.fieldOf("value1").forGetter(data -> data.value1),
Codec.BOOL.fieldOf("value2").forGetter(data -> data.value2)
).apply(instance, ExampleSavedData::new));
);
private final ServerLevel level;
private final int value1;
private final boolean value2;
// For the new instance
private ExampleSavedData(ServerLevel.Context ctx) {
this(ctx.levelOrThrow(), 0, false);
}
// For the codec
// The constructors don't need to be public if not using `DimensionDataStorage#set`
private ExampleSavedData(ServerLevel level, int value1, boolean value2) {
this.level = level;
this.value1 = value1;
this.value2 = value2;
}
// Other methods here
}
// With access to the DimensionDataStorage storage
ExampleSavedData data = storage.computeIfAbsent(ExampleSavedData.TYPE);
net.minecraft.server.ServerScoreboarddataFactoryis removedcreateDatanow takes in a$Packedinstance
net.minecraft.world.RandomSequencesfactory,loadis removedcodec- Constructs a codec for the random sequence given the current world seed.
net.minecraft.world.entity.raid.Raidsno longer takes in anythinggetType- Returns the saved data type based on the current dimension.factoryis removedticknow takes in theServerLevelgetId- Gets the identifier for the raid instance.canJoinRaidno longer takes in the raid instanceloadno longer takes in theServerLevel
net.minecraft.world.level.levelgen.structure.structures.StructureFeatureIndexSavedDatafactory,loadis removedtype- Returns the feature saved data type with its specified id.
net.minecraft.world.level.saveddataSavedDatasaveis removed$Factoryrecord is removed$Context- Holds the current context that the saved data is being written to.
SavedDataType- A record that represents the type of the saved data, including information on how to construct, save, and load the data.
net.minecraft.world.level.saveddata.mapsMapIndexnow has a constructor to take in the last map idfactory,loadis removedgetFreeAuxValueForMap->getNextMapId
MapItemSavedDatafactory,loadis removedtype- Returns the saved data type using the map id's key.
net.minecraft.world.level.storage.DimensionDataStoragenow takes in aSavedData$ContextcomputeIfAbsent,getnow take in only theSavedDataTypesetnow takes in theSavedDataTypealong with the data instance
net.minecraft.world.scores.ScoreboardSaveDataload->loadFrompack- Packs the data into its saved data format.$Packed- Represents the serializable packed data.
Render Pipeline Rework
Rendering an object to the screen, whether through a shader or a RenderType, has been fully or partially reworked, depending on what systems you were using previously. As such, a lot of things need to be reexplained, which a more in-depth look will be below. However, for the people who don't care, here's the TL;DR.
First, shader JSONs no longer exist. This is replaced by a RenderPipeline, which is effectively an in-code substitute. Second, the RenderPipelines forcibly make most abtrarily values into objects. For example, instead of storing the blend function mode id, you store a BlendFunction object. Similarly, you no longer store or setup the direct texture objects, but instead manage it through a GpuTexture. Finally, the VertexBuffer can either draw to the framebuffer by directly passing in the RenderPipeline, updating any necessary uniforms in the consumer, or by passing in the RenderType.
Now, for those who need the details, let's jump into them.
Abstracting Open GL
As many are aware, Minecraft has been abstracting away their OpenGL calls and constants, and this release is no different. All of the calls to GL codes, except BufferUsage, have been moved out of object references, to be obtained typically by calling GlConst$toGl. However, with all of the other rendering reworks, there are numerous changes and complexities that require learning an entirely new system, assuming you're not using RenderTypes.
Starting from the top, all calls to the underlying render system goes through GpuDevice, an interface that acts like a general implementation of a render library like OpenGL or Vulkan. The device is responsible for creating buffers and textures, executing whatever commands are desired. Getting the current GpuDevice can be accessed through the RenderSystem via getDevice like so:
GpuDevice device = RenderSystem.getDevice();
The GpuDevice can the create either buffers with the desired data or a texture containing information on what to render using createBuffer and createTexture, respectively. Just for redundancy, buffers hold the vertex data while textures hold the texture (color and depth) data. You should generally cache the buffer or texture object for later use with any additional data updated as needed. For reference, buffers are typically created by using a BufferBuilder with a ByteBufferBuilder to build the MeshData first, before passing that into createBuffer.
With the desired buffers and textures set up, how do we actually modify render them to the screen? Well, this is handled through the CommandEncoder, which can also be optained from the device via GpuDevice#createCommandEncoder. The encoder contain the familiar read and write methods along with a few extra to clear texture to a given color or simply blit the the texture immediately to the screen (presentTexture). However, the most important method here is createRenderPass. This takes in the GpuTexture to draw to the screen along with a default ARGB color for the background. Additionally, it can take in a depth texture as well. This should be created using a try with resources block like so:
// We will assume you have constructed a `GpuTexture` texture for the color data
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(this.texture, OptionalInt.of(0xFFFFFFFF))) {
// Setup things here
}
Within the RenderPass, you can set the RenderPipeline to use, which defines the associated shaders, bind any samplers from other targets or set uniforms, scissor a part of a screen to render, and set the vertex and index buffers used to define the vertices to render. Finally, everything can be drawn to the screen using one of the draw methods, providing the starting index and the vertex count.
// If the buffers/textures are not created or cached, create them here
// Any methods ran from `CommandEncoder` cannot be run while a render pass is open
RenderSystem.AutoStorageIndexBuffer indices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS);
GpuBuffer vertexBuffer = RenderSystem.getQuadVertexBuffer();
GpuBuffer indexBuffer = indices.getBuffer(6);
// We will assume you have constructed a `GpuTexture` texture for the color data
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(this.texture, OptionalInt.of(0xFFFFFFFF))) {
// Set pipeline information along with any samplers and uniforms
pass.setPipeline(EXAMPLE_PIPELINE);
pass.setVertexBuffer(0, vertexBuffer);
pass.setIndexBuffer(indexBuffer, indices.type());
pass.bindSampler("Sampler0", RenderSystem.getShaderTexture(0));
// Then, draw everything to the screen
// In this example, the buffer just contains a single quad
// For those unaware, the vertex count is 6 as a quad is made up of 2 triangles, so 2 vertices overlap
pass.drawIndexed(0, 6);
}
However, unless you need such fine control, it is recommended to use a RenderType with the MultiBufferSource when necessary as that sets up most things for you.
Object References
Most raw references to GL codes used for determining the mode and handling the texture have been replaced with objects. As the TL;DR previously mentioned, these are stored typically as some sort of enum or object that can then be resolved to their GL counterparts. Some objects contain their reference identifier directly, like BlendFunction. Others are simply placeholders that are resolved in their appropriate location, like DepthTestFunction whose enum values are converted via RenderPipeline#toGl.
However, the biggest change is the addition of the GpuTexture. This is responsible for managing anything to do with creating, writing, and releasing a texture written to some buffer. At initialization, the texture is created and bound, with any necessary parameters set for mipmaps and texture formats. These GpuTextures are stored and referenced everywhere, from the depth and color targets for a RenderTarget to the texture backing a TextureAtlas. Then, once no longer need, the texture is released by calling #close. Note that although technically #bind can be called again, the texture is already considered deleted and should not be used.
If, for some reason, you need to use a GpuTexture, it's actually quite simple to use. First, you just construct the GpuTexture via GpuDevice#createTexture. Then, if you need to change any of the addressing or texture mipmap filters, you can apply them whenever before writing.
public class MyTextureManager {
private final GpuTexture texture;
public MyTextureManager() {
this.texture = RenderSystem.getDevice().createTexture(
// The texture name, used for logging and debugging
"Example Texture",
// The format of the texture pixels, can be one of three values that
// Values: (texture internal format, texel data format, texel data type, pixel size)
// - RGBA8 (GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, 4)
// - RED8 (GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1)
// - DEPTH32 (GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, 4)
TextureFormat.RGBA8,
// Width of the texture
16,
// Height of the texture
16,
// The mipmap level and maximum level-of-detail (minimum of 1)
1
);
// Set the texture mode for the UV component
// Values:
// - REPEAT (GL_REPEAT)
// - CLAMP_TO_EDGE (GL_CLAMP_TO_EDGE)
this.texture.setAddressMode(
// The mode to use for the U component (GL_TEXTURE_WRAP_S)
AddressMode.CLAMP_TO_EDGE,
// The mode to use for the V component (GL_TEXTURE_WRAP_R)
AddressMode.REPEAT
);
// Sets the filter functions used for scaling the texture on the screen
// Values (default, for mipmaps):
// - NEAREST (GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR)
// - LINEAR (GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR)
this.texture.setTextureFilter(
// The mode to use for the texture minifying function (GL_TEXTURE_MIN_FILTER)
FilterMode.LINEAR,
// The mode to use for the texture magnifying function (GL_TEXTURE_MAG_FILTER)
FilterMode.NEAREST,
// Whether mipmaps should be used for the minifying function (should have a higher mipmap level than 1 when true)
false
);
}
}
Then, whenever you want to upload something to the texture, you call CommandEncoder#writeToTexture or CommandEncoder#copyTextureToTexture. This either takes in the NativeImage to write from or an IntBuffer with the texture data and a NativeImage$Format to use.
// Like other buffer/texture modification methods, this must be done outside of a render pass
// We will assume you have some `NativeImage` image to load into the texture
RenderSystem.getDevice().createCommandEncoder().writeToTexture(
// The texture (destination) being written to
this.texture,
// The image (source) being read from
image,
// The mipmap level
0,
// The starting destination x offset
0,
// The starting destination y offset
0,
// The destination width (x size)
16,
// The desintation height (y size)
16,
// The starting source x offset
0,
// The starting source y offset
0
)
Finally, once you're done with the texture, don't forget to release it via #close if it's not already handled for you.
Render Pipelines
Previously, a pipeline was constructed using a JSON that contained all metadata from the vertex and fragement shader to their defined values, samplers, and uniforms. However, this has all been replaced with an in-code solution that more localizes some parts of the JSON and some parts that were relegated to the RenderType. This is known as a RenderPipeline.
A RenderPipeline can be constructed using its builder via RenderPipeline#builder. A pipeline can then be built by calling build. If you want the shader to be pre-compiled without any additional work, the final pipeline can be passed to RenderPipeline#register. However, you can also handle the compilation yourself if more graceful fail states are desired. If you have snippets that are used across multiple pipelines, then a partial pipeline can be built via $Builder#buildSnippet and then passed to the constructing pipelines in the builder method.
The following enums described in the examples have their GL codes provided with them as they have been abstracted away.
// This assumes that RenderPipeline#register has been made public through some form
public static final RenderPipeline EXAMPLE_PIPELINE = RenderPipelines.register(
RenderPipeline.builder()
// The name of the pipeline (required)
.withLocation(ResourceLocation.fromNamespaceAndPath("examplemod", "pipeline/example"))
// The location of the vertex shader, relative to 'shaders' (required)
// Points to 'assets/examplemod/shaders/example.vsh'
.withVertexShader(ResourceLocation.fromNamespaceAndPath("examplemod", "example"))
// The location of the fragment shader, relative to 'shaders' (required)
// Points to 'assets/examplemod/shaders/example.fsh'
.withFragmentShader(ResourceLocation.fromNamespaceAndPath("examplemod", "example"))
// The format of the vertices within the shader (required)
.withVertexFormat(
// The vertex format
DefaultVertexFormat.POSITION_TEX_COLOR,
// The mode of the format
VertexFormat.Mode.QUADS
)
// Adds constants that can be referenced within the shaders
// Can specify a name in addition to an int / float to represent its value
// If no value is specified, then it should be gated with a #ifdef / #endif block
.withShaderDefines("ALPHA_CUTOUT", 0.5)
// Adds the texture sampler2Ds that can be referenced within the shaders
// Typically, the shader textures stored in the `RenderSystem` is referenced via `Sampler0` - `Sampler11`
// - `Sampler0` is usually always present, but these should be set up beforehand
// Additionally, for render targets, `InSampler` is typically present, along with any defined in a postpass
.withSampler("Sampler0")
// Adds uniforms that can be referenced within the shaders
// These are just definitions which are then populated by default or by the caller depending on the scenario
// Defaults can be found in `CompiledShaderProgram#setupUniforms`
.withUniform("ModelOffset", UniformType.VEC3)
// Custom uniforms must be set manually as the vanilla batching system does not support such an operation
.withUniform("CustomUniform", UniformType.INT)
// Sets the depth test functions used rendering objects at varying distances from the camera
// Values:
// - NO_DEPTH_TEST (GL_ALWAYS)
// - EQUAL_DEPTH_TEST (GL_EQUAL)
// - LEQUAL_DEPTH_TEST (GL_LEQUAL)
// - LESS_DEPTH_TEST (GL_LESS)
// - GREATER_DEPTH_TEST (GL_GREATER)
.withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST)
// Sets how the polygons should render
// Values:
// - FILL (GL_FILL)
// - WIREFRAME (GL_LINE)
.withPolygonMode(PolygonMode.FILL)
// When true, can cull front or back-facing polygons
.withCull(false)
// Specifies the functions to use when blending two colors with alphas together
// Made up of the `GlStateManager$SourceFactor` and `GlStateManager$DestFactor`
// First two are for RGB, the last two are for alphas
// If nothing is specified, then blending is disabled
.withBlend(BlendFunction.TRANSLUCENT)
// Determines whether to mask writing colors and alpha to the draw buffer
.withColorWrite(
// Mask RGB
false,
// Mask alpha
false
)
// Determines whether to mask writing values to the depth buffer
.withDepthWrite(false)
// Determines the logical operation to apply when applying an RGBA color to the framebuffer
.withColorLogic(LogicOp.NONE)
// Sets the scale and units used to calculate the depth values for the polygon.
// This takes the place of the polygon offset.
.withDepthBias(0f, 0f)
.build()
);
From there, the pipeline can either be used directly or through some RenderType:
// This will assume that RenderType#create is made public
public static final RenderType EXAMPLE_RENDER_TYPE = RenderType.create(
// The name of the render type
"examplemod:example",
// The size of the buffer
// Or 4MB
4194304,
// Whether it effects crumbling that is applied to block entities
false,
// Whether the vertices should be sorted before upload
true,
// The pipeline to use
EXAMPLE_PIPIELINE,
// Any additional composite state settings to apply
RenderType.CompositeState.builder().createCompositeState(RenderType.OutlineProperty.NONE)
);
The pipeline can then be drawn by creating the RenderPass and setting the RenderPipeline to use your pipeline. As for the RenderType, the associated buffer can be obtained using MultiBufferSource#getBuffer. Note that custom uniforms should not be used within RenderTypes as they cannot be set easily.
// Since we are using a custom uniform, we must handle it ourselves
// We will assume we have some `GpuTexture` texture to write to
// Create the render pass to use
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(
// The GPU color texture to write to
this.texture,
// The clear color in ARGB format
OptionalInt.of(0xFFFFFFFF),
// The depth texture and the clear depth value can also be constructed here
)
) {
// Add the pipeline and our uniform
pass.setPipeline(EXAMPLE_PIPELINE);
pass.setUniform("CustomUniform", 1);
// Set any additional sampler and the vertex/index buffers to use
// Finally, call one of the draw functions
// Takes in the first index and the index count to draw for the vertices
pass.draw(...);
}
Post Effects
Given that the pipeline JSONs have been stripped, this also effects the post effects. The program is replaced with directly specifying the vertex_shader and the fragment_shader. Additionally, uniforms must specify their type.
// Before 1.21.5 (for some pass in 'passes')
{
// Same as before
"inputs": [ /*...*/ ],
"output": "swap",
// Replaced by 'vertex_shader', 'fragement_shader'
"program": "minecraft:post/box_blur",
"uniforms": [
{
"name": "BlurDir",
// Required
"values": [ 1.0, 0.0 ]
},
{
"name": "Radius",
// Required
"values": [ 0.0 ]
}
]
}
// 1.21.1 (for some pass in 'passes')
{
// Same as before
"inputs": [ /*...*/ ],
"output": "swap",
// Relative to 'shaders'
// Points to 'assets/minecraft/shaders/post/blur.vsh'
"vertex_shader": "minecraft:post/blur",
// Points to 'assets/minecraft/shaders/post/box_blur.fsh'
"fragment_shader": "minecraft:post/box_blur",
"uniforms": [
{
"name": "BlurDir",
// Specifies the type to use for this uniform
// One of `Uniform$Type`:
// - int
// - ivec3
// - float
// - vec2
// - vec3
// - vec4
// - matrix4x4
"type": "vec2",
"values": [ 1.0, 0.0 ]
},
{
"name": "Radius",
"type": "float"
// Values are no longer required
}
]
}
Note that if you do not define a value for a uniform, they still must be specified before processing the PostChain by calling #setUniform within the RenderPass consumer of PostChain#process.
// Assume we already got the `PostChain` post
post.process(Minecraft.getInstance().getMainRenderTarget(), GraphicsResourceAllocator.UNPOOLED, pass -> {
pass.setUniform("Radius", 0.4f);
});
com.mojang.blaze3d.GpuOutOfMemoryException- An exception thrown when a texture could not be allocated on the GPU.com.mojang.blaze3d.buffersBufferTypeno longer stores the GL codes, now inGlConst#toGlBufferUsageno longer stores the GL codes, now inGlConst#toGlisReadable,isWritable- Returns whether the buffer can be read from or written to.
GpuBufferis now abstract- Constructor with
ByteBufferis removed size- Returns the size of the buffer.type- Returns the type of the buffer.resize,write,read,bindis removedusage- Returns the usage of the buffer.closeis now abstractisClosed- Returns whether the buffer has been closed.$ReadViewis now an interface that defines the buffer data and how to close the view
- Constructor with
com.mojang.blaze3d.font.SheetGlyphInfo#uploadnow takes in aGpuTexturecom.mojang.blaze3d.openglDirectStateAccess- An interface that creates and binds data to some framebuffer.$Core- An implementation of DSA that modifies the framebuffer without binding them to the context.$Emulated- An abstraction over DSA that still binds the context.
GlBuffer- An implementation of theGpuBufferfor OpenGL.GlCommandEncoder- An implementation of theCommandEncoderfor OpenGL.GlDebugLabel- A labeler for handling debug references to GL-specified data structures.GlDevice- An implementation ofGpuDevicefor OpenGL.GlRenderPass- An implementation ofRenderPassfor OpenGL.GlRenderPipeline- An implementation ofCompiledRenderPipelinefor OpenGL.GlTexture- An implementation ofGpuTexturefor OpenGL.VertexArrayCache- A cache for binding and uploading a vertex array to the OpenGL pipeline.
com.mojang.blaze3d.pipelineBlendFunction- A class that holds the source and destination colors and alphas to apply when overlaying pixels in a target. This also holds all vanilla blend functions.CompiledRenderPipeline- An interface that holds the pipeline with all necessary information to render to the screen.RenderPipeline- A class that contains everything required to render some object to the screen. It acts similarly to a render state before being applied.RenderTargetnow takes in a string representing the name of the targetcolorTextureId->colorTexture, now aGpuTexture- Same with
getColorTextureId->getColorTexture
- Same with
depthBufferId->depthTexture, now aGpuTexture- Same with
getDepthTextureId->getDepthTexture
- Same with
filterModeis now aFilterMode- Same with
setFilterModefor the int parameter
- Same with
blitAndBlendToScreenno longer takes in the viewport size parametersframebufferIdis removedcheckStatusis removedbindWrite,unbindWrite,setClearColoris removedblitToScreenno longer takes in any parametersblitAndBlendToScreen->blitAndBlendToTexture, not one-to-oneclearis removedunbindReadis removed
com.mojang.blaze3d.platformDepthTestFunction- An enum representing the supported depth tests to apply when rendering a sample to the framebuffer.DisplayDatais now a recordwithSize- Creates a new instance with the specified width/height.withFullscreen- Creates a new instance with the specified fullscreen flag.
FramerateLimitTrackergetThrottleReason- Returns the reason that the framerate of the game was throttled.isHeavilyThrottled- Returns whether the current throttle significantly impacts the game speed.$FramerateThrottleReason- The reason the framerate is throttled.
GlConst->com.mojang.blaze3d.opengl.GlConst#toGl- Maps some reference object to its associated OpenGL code.
GlDebug->com.mojang.blaze3d.opengl.GlDebugenableDebugCallbacknow takes in a set of the enabled extensions.
GlStateManager->com.mojang.blaze3d.opengl.GlStateManager_blendFunc,_blendEquationis removed_glUniform2(int, IntBuffer),_glUniform4(int, IntBuffer)is removed_glUniformMatrix2(int, boolean, FloatBuffer),_glUniformMatrix3(int, boolean, FloatBuffer)is removed_glUniformMatrix4(int, boolean, FloatBuffer)->_glUniformMatrix4(int, FloatBuffer), transpose is now always false_glGetAttribLocationis removed_glMapBufferis removed_glCopyTexSubImage2Dis removed_glBindRenderbuffer,_glDeleteRenderbuffersis removedglGenRenderbuffers,_glRenderbufferStorage,_glFramebufferRenderbufferis removed_texParameter(int, int, float)is removed_genTextures,_deleteTexturesis removed_texSubImage2Dnow has an overload that takes in anIntBufferinstead of alongfor the pixel datauploadis removed_stencilFunc,_stencilMask,_stencilOp,_clearStencilis removed_getTexImageis removed_glDrawPixels,_readPixelsis removed$CullState#modeis removed$DestFactor->DestFactor, codes are removed to be called throughGlConst#toGl$FramebufferStateenum is removed$LogicOp->LogicOp, codes are removed to be called throughGlConst#toGl- All but
OR_REVERSEis removed NONE- Performs no logic operation.
- All but
$PolygonOffsetState#lineis removed$SourceFactor->SourceFactor, codes are removed to be called throughGlConst#toGl$StencilFunc,$StencilStateclass is removed$Viewportenum is removed
GlUtilclass is removedgetVendor,getRenderer,getOpenGlVersion(nowgetVersion) have been moved to instance abstract methods onGpuDevicegetCpuInfo->GLX#_getCpuInfo
GLXgetOpenGLVersionStringis removed_init->_getCpuInfo, not one-to-one_renderCrosshair,com.mojang.blaze3d.systems.RenderSystem#renderCrosshair->net.minecraft.client.gui.components.DebugScreenOverlay#render3dCrosshair, not one-to-one
PolygonMode- A enum that defines how the polygons will render in the buffer.NativeImageconstructor is now publicuploadis removedgetPointer- Returns the pointer to the image data.setPixelABGRis now publicapplyToAllPixelsis removeddownloadTexture,downloadDepthBufferis removedflipYis removedsetPackPixelStoreState,setUnpackPixelStoreStateis removed$InternalGlFormatenum is removed$Formatno longer contains the GL codes, now inGlConst#toGl
TextureUtilgenerateTextureId,releaseTextureIdis removedprepareImageis removedwriteAsPNGnow takes in aGpuTextureinstead of the direct three integers- The overload without the
IntUnaryOperatoris removed
- The overload without the
com.mojang.blaze3d.resourceRenderTargetDescriptornow takes in an integer representing the color to clear toResourceDescriptorprepare- Prepares the resource for use after allocation.canUsePhysicalResource- Typically returns whether a descriptor is already allocated with the same information.
com.mojang.blaze3d.shadersAbstractUniform->com.mojang.blaze3d.opengl.AbstractUniformsetSafemethods are removedsetMat*methods are removedset(Matrix3f)is removed
CompiledShader->com.mojang.blaze3d.opengl.GlShaderModule$Type->com.mojang.blaze3d.shaders.ShaderType
Uniform->com.mojang.blaze3d.opengl.Uniform- Constructor now takes in a
$Typeinstead of the count and an integer representing the type UT_*fields are removedsetFromConfig(ShaderProgramConfig.Uniform)is removedgetTypeFromStringis removedgetTypenow returns a$Typeset(int, float)is removedsetSafeis now private$Type- Holds the type name as well as how many values it holds.getLocationis removedgetCount->$Type#countgetIntBuffer,getFloatBufferis removed$Type->com.mojang.blaze3d.shaders.UniformType
- Constructor now takes in a
com.mojang.blaze3d.systemsCommandEncoder- An interface that defines how to encode various commands to the underlying render system, such as creating a pass, clearing and writing textures, or reading from the buffer.GpuDevice- An interface that defines the device or underlying render system used to draw to the screen. This is responsible for creating the buffers and textures while compiling any pipelines.RenderPass- An interface that defines how a given pass is rendered to some buffer using the underlying render system. This allows binding any samplers and setting the required uniforms.RenderSystemisOnRenderThreadOrInit,assertOnRenderThreadOrInitis removedrecordRenderCall,replayQueueis removedblendFunc,blendFuncSeparate,blendEquationis removedtexParameter,deleteTexture,bindTextureForSetupis removedstencilFunc,stencilMask,stencilOpis removedclearDepthis removedglBindBuffer,glBindVertexArray,glBufferData,glDeleteBuffersis removedglUniform1iis removedglUniform1,glUniform2,glUniform3,glUniform4is removedglUniformMatrix2,glUniformMatrix3,glUniformMatrix4is removedsetupOverlayColornow takes in aGpuTextureinstead of two intsbeginInitialization,finishInitializationis removedrenderThreadTesselatoris removedsetShader,clearShader,getShaderis removedsetShaderTexturenow takes in aGpuTextureinstead of a bind addressgetShaderTexturenow returns aGpuTextureor null if not presentpixelStore,readPixelsis removedqueueFencedTask,executePendingTasks- Handles sending tasks that run on the GPU asyncronously.SCISSOR_STATE- Holds the main scissor state.disableDepthTest,enableDepthTestis removeddepthFunc,depthMaskis removedenableBlend,disableBlendis removedneableCull,disableCullis removedpolygonMode,enablePolygonOffset,disablePolygonOffset,polygonOffsetis removedenableColorLogicOp,disableColorLogicOp,logicOpis removedbindTexture,viewportis removedcolorMask,clearColor,clearis removedsetupShaderLights(CompiledShaderProgram)is removedgetShaderLights- Returns the vectors representing the block and sky lights.drawElements,getStringis removedinitRenderernow takes in the window pointer, the default shader source, and a boolean of whether to use debug labelssetupDefaultStateno longer takes in any parametersmaxSupportTextureSizeis removedglDeleteVertexArraysis removeddefaultBlendFuncis removedsetShaderTextureis removedgetQuadVertexBuffer- Returns a vertex buffer with a quad bound to it.getDevice,tryGetDevice- Returns theGpuDevicerepresenting the underlying render system to use.getCapsStringis removedactiveTextureis removedsetModelOffset,resetModelOffset,getModelOffset- Handles the offset to apply to a model when rendering for the uniformModelOffset. Typically for clouds and world borders.$AutoStorageIndexBuffer#bind->getBuffer, not one-to-one$GpuAsyncTask- A record that holds the callback and fence object used to sync information to the GPU.
ScissorState- A class which holds the part of the screen to render.
com.mojang.blaze3d.texturesAddressMode- The mode set for how to render a texture to a specific location.FilterMode- The mode set for how to render a texture whenever the level-of-detail function determines how the texture should be maximized or minimized.GpuTexture- A texture that is bound and written to the GPU as required.TextureFormat- Specifies the format that the texture should be allocated with.
com.mojang.blaze3d.vertexPoseStackmulPose(Quaternionf),rotateAroundnow takes in aQuaternionfcinstead of aQuaternionfclear->isEmptymulPose(Matrix4f)->mulPose(Matrix4fc)$PosecomputeNormalMatrixis now privatetransformNormalnow takes in aVector3fcas its first parametertranslate,scale,rotate,rotateAround,setIdentity,mulPoseare now available on the pose itself in addition to the stack
VertexBuffer->com.mojang.blaze3d.buffers.GpuBuffer, not one-to-one- Some logic is also moved to
VertexFormat
- Some logic is also moved to
VertexFormatbindAttributesis removedsetupBufferState,clearBufferState,getImmediateDrawVertexBuffer->uploadImmediateVertexBuffer,uploadImmediateIndexBuffer; not one-to-one$IndexTypeno longer stores the GL codes, now inGlConst#toGl$Modeno longer stores the GL codes, now inGlConst#toGl
VertexFormatElementsetupBufferStateis removed$Typeno longer stores the GL codes, now inGlConst#toGl$Usageno longer stores the GL function calls, now inVertexArrayCache#setupCombinedAttributes
com.mojang.mathMatrixUtilisIdentity,isPureTranslation,isOrthonormalnow take in aMatrix4fccheckProperty- Checks if the provided property is represented within the matrix.
OctahedralGrouptransformationnow returns aMatrix3fcfromAnges->fromXYAngles, not one-to-one
Quadrant- An enum that contains rotations in 90 degree increments.SymmetricGroup3#transformationnow returns aMatrix3fcTransformationnow takes in aMatrix4fcgetMatrixnow returns aMatrix4fcgetMatrixCopy- Returns a deep copy of the current matrix.
net.minecraft.client.gui.font.FontTexturenow takes in a supplied label stringnet.minecraft.client.main.GameConfignow takes in a boolean representing whether to render debug labelsnet.minecraft.client.rendererCloudRenderer#renderno longer takes in theMatrix4fs used for projection or posingCompiledShaderProgram->com.mojang.blaze3d.opengl.GlProgramlinknow takes in a string for the shader namesetupUniformsnow take in the list of$UniformDescriptions along with a list of names used by the samplersgetUniformConfigis removedbindSamplernow takes in aGpuTextureinstead of the integer bind identifierparseUniformNodeis removed
CoreShaders->RenderPipelines, not one-to-oneLightTexture#getTarget- Returns theGpuTexturethat contains the light texture for the current level based on the player.PostChainloadno longer takes in theShaderManager, now taking in aResourceLocationrepresenting the name of the chainaddToFrame,processnow takes in aRenderPassconsumer to apply any additional settings to the pass to rendersetUniformis removedsetOnRenderPass- Sets the uniform within the post chain on theRenderPassfor use in the shaders.
PostChainConfig$Passnow takes in the ids of the vertex and fragment shader instead of the program idreferencedTargets- Returns the targets referenced in the pass to apply.programis removed
$Uniformnow takes in the type of the uniform along with an optional list of floats if the value does not need to be overridden
PostPassno longer takes in theCompiledShaderProgram, now taking in theRenderPipelineinstead of a string representing the name of the passaddToFramenow takes in aRenderPassconsumer to apply any additional settings to the pass to rendergetShaderis removed$Input#bindTonow takes in aRenderPassinstead of theCompiledShaderProgram
RenderStateShard$LayerStateShards using polygon offsets have been removedgetName- Returns the name of the shard.$TransparencyStateShardclass is removed- Now handled through
BlendFunction
- Now handled through
$ShaderStateShardclass is removed- Directly referred to by the
VertexBuffer
- Directly referred to by the
$CullStateShardclass is removed- Now handled as a setting on the
RenderPipeline
- Now handled as a setting on the
$DepthTestStateShardclass is removed- Now handled through
DepthTestFunction
- Now handled through
$WriteMaskStateShardclass is removed- Now handled as a setting on the
RenderPipeline
- Now handled as a setting on the
$ColorLogicStateShardclass is removed- Now handled as a setting on the
RenderPipeline
- Now handled as a setting on the
$OutputStateShardnow takes in a suppliedRenderTargetinstead of the runnables for the startup and teardown states
RenderTypeno longer takes in theVertexFormatorVertexFormat$ModeSKY,END_SKY,sky,endSky,starsis removedENTITY_OUTLINE_BLIT,entityOutlineBlitis removedPANORAMA,panoramais removedCREATE_LIGHTMAP,createLightmapis removedcreateClouds,flatClouds,clouds,cloudsDepthOnlyis removedworldBorderis removeddebugLine- Returns theRenderTypeassociated with the debug line.entityOutlineBlit- Returns theRenderTypeused for rendering an entity outline.panorama- Returns theRenderTypeused for rendering panorama mode.createLightmap- Returns theRenderTypeused for rendering the lightmap texture.createno longer takes in theVertexFormatorVertexFormat$Mode, instead theRenderPipelinegetRenderTarget,getRenderPipeline- Returns the target and pipeline used for rendering.format,mode,draware now abstract$CompositeStateBuildermethods are now protected$OutlinePropertyis now protected
ShaderDefines$Builder#definenow has an overload that takes in an integerShaderManagerSHADER_INCLUDE_PATHis now privateMAX_LOG_LENGTHis removedpreloadForStartupis removed, replaced byGpuDevice#precompilePipelinegetProgram,getProgramForLoading->getShader, not one-to-onelinkProgramnow takes in aRenderPipelineinstead of aShaderProgramandShaderProgramConfig$CompilationCache#getOrCompileProgram,getOrCompileShader->getShaderSource, not one-to-one$Configsno longer takes in the map of programs$ShaderCompilationKeyrecord is removed
ShaderProgram,ShaderProgramConfig->RenderPipeline, not one-to-oneSkyRenderer#renderDarkDiscno longer takes in thePoseStack
net.minecraft.client.renderer.chunk.SectionRenderDispatcheruploadSectionLayer,uploadSectionIndexBuffer->$RenderSection#uploadSectionLayer,uploadSectionIndexBuffer$SectionBuffers- A class that holds the buffers used to render the sections.
net.minecraft.client.renderer.textureAbstractTextureNOT_ASSIGNEDis removedtexture,getTexture- Holds the reference to the texture to render.getId,releaseIdis removedbindis removed
DynamicTexturenow takes in the label of the textureSpriteContents#uploadFirstFrame,$AnimatedTexture#uploadFirstFramenow takes in aGpuTextureSpriteTicker#tickAndUploadnow takes in theGpuTextureTextureAtlasSprite#uploadFirstFrame,$Ticker#tickAndUploadnow takes in theGpuTexture
Model Rework
The model system has been further separated into models for block states, blocks, and items. As such, the unifying BakedModel has been completely removed and separated into their own sections, loaded in three steps: from JSON, resolving dependencies, and then baking for use with the associated block state model or item model. For reference, everything discussed below is what's happenening within ModelManager#reload in parallel.
First, let's start from the base model JSON used between blocks and items. These are loaded into an UnbakedModel (specifically BlockModel) which contains the familiar properties such as gui light and texture slots. However, one change is the splitting of the elements from their render settings. These elements that hold the render quads are stored in an UnbakedGeometry. The UnbakedGeometry is responsible for baking the model into a QuadCollection, which effectively holds the list of BakedQuads to render. Currently, vanilla only has the SimpleUnbakedGeometry, which holds the familiar list of BlockElements. These UnbakedModel, once loaded, are then passed to the ModelDiscovery for resolving the block state and item models.
Next we have the ResolvableModels, which is the base of both block state and item models. These models essentially function as markers requesting the UnbakedModels that they will be using. From there, we have their subtypes BlockStateModel$UnbakedRoot for the block state JSON and ItemModel$Unbaked for the model referenced in the client item JSON. Each of these implement resolveDependencies in some way to call ResolvableModel$Resolver#markDependency with the model location they would like to use.
Technically,
BlockStateModels are a bit more complex as variants useBlockStateModel$Unbakedduring loading which are then transformed into an$UnbakedRootduring initialization.
Now that we know what models that should be loaded, they now have to be put into a usable state for baking. This is the job of the ModelDiscovery, which takes in a ResolvableModel and loads the UnbakedModels into a ResolvedModel on first reference. ResolvedModels are functionally wrappers around UnbakedModels used to resolve all dependency chains, as the name implies.
From there, model groups are built for BlockStates and the textures are loaded, leading to the final step of actually baking the BlockStateModel and the ItemModel. This is handled through the bake methods provided on the $UnbakedRoot (or $Unbaked) and the ModelBakery. In a nutshell, bake constructs the list of BakedQuads stored with whatever additional information is desired by the block state or item model itself. The ResolvedModels are obtained from the baker, from which the instance methods are called. For BlockStateModels, this is resolved via SimpleModelWrapper#bake, from which the ModelState is obtained from the Variant data. They stored the baked quads in a BlockModelPart. For ItemModels, it just consumes the BakedQuads list directly along with information provided by ModelRenderProperties#fromResolvedModel. This does mean that each BlockStateModel and ItemModel may contain duplicated (but unique) BakedQuads if the same model is referenced in multiple locations.
Block Generators: The Variant Mutator
Given all the changes that separated out the block state JSON loading, there have also been a number of changes to the BlockModelGenerators. While most of them are simply renames (e.g., BlockStateGenerator -> BlockModelDefinitionGenerator), the major change is the addition of the VariantMutator. The VariantMutator is functionally a UnaryOperator on a Variant used to set some setting. This addition has simplified (or more like codec construction) the use of the PropertyDispatch for more quickly dispatching blocks with variants based on their properties.
// Creates a property dispatch on the horizontal facing property
// Applies the associated variants, though if desired, a functional interface can be provided instead
public static final PropertyDispatch<VariantMutator> ROTATION_HORIZONTAL_FACING = PropertyDispatch.modify(BlockStateProperties.HORIZONTAL_FACING)
.select(Direction.EAST, BlockModelGenerators.Y_ROT_90)
.select(Direction.SOUTH, BlockModelGenerators.Y_ROT_180)
.select(Direction.WEST, BlockModelGenerators.Y_ROT_270)
.select(Direction.NORTH, BlockModelGenerators.NOP);
// Then, with access to the `Consumer<BlockModelDefinitionGenerator>` blockStateOutput
this.blockStateOutput.accept(
MultiVariantGenerator.dispatch(EXAMPLE_BLOCK).with(ROTATION_HORIZONTAL_FACING)
);
net.minecraft.client.data.modelsBlockModelGeneratorsnonOrientableTrapdoor->NON_ORIENTABLE_TRAPDOOR, now static- Constants are now available for common
VariantMutators, like rotating the block model some number of degrees texturedModels->TEXTURED_MODELS, now staticMULTIFACE_GENERATORis now privateplainModel- Creates a variant from the model location.variant,variants- Creates a regularMultiVariantfrom some number ofVariantsplainVariant- Creates aMultiVariantwith only one model from its location.condition- Creates a new condition builder for multipart modelsor- ORs multiple conditions together.- Most generator methods now return the
BlockModelDefinitionGenerator,Variant, orMultiVariantand take in aVariantorMultiVariantinstead of aResourceLocationpointing to the desired modelVariantPropertieshave been replaced withVariantMutatorsCondition$TerminalConditionis replaced withCondition
createHorizontalFacingDispatch,createHorizontalFacingDispatchAlt,createTorchHorizontalDispatchis removedcreateFacingDispatchis removedcreateRotatedVariant(Block, ResourceLocation)is removedselectMultifaceProperties- Creates a map of properties toVariantMutators based on the providedBlockStateand direction to property function.applyRotationno longer takes in theVariantand returns aVariantMutator
ItemModelGenerators#generateSpawnEggis removedModelProvider#saveAllis removed
net.minecraft.client.data.models.blockstatesBlockStateGenerator->BlockModelDefinitionGenerator, not one-to-oneCondition->net.minecraft.client.renderer.block.model.multipart.Condition, not one-to-onevalidate->instantiate, not one-to-one
ConditionBuilder- Builds a condition using property valuesMultiPartGeneratornow implementsBlockModelDefinitionGeneratorwith(List<Variant>)->with(MultiVariant)with(Variant)is removedwith(Condition, ...)->with(Condition, MultiVariant)- Overload taking in
ConditionBuilder
- Overload taking in
$ConditionalEntry,$Entryis removed
MultiVariantGeneratornow implementsBlockModelDefinitionGeneratormultiVariant->dispatchmultiVariant(Block, ...)->dispatch(Block, MultiVariant)$Empty- A multi variant entry that matches every block state.
PropertyDispatchhas a generic containing the value of the dispatch- The generic
Vreplaces all values ofList<Variant> property,properties->initialormodify$C*#generateListmethods are removed$*Functionare removed
- The generic
Selector->PropertyValueList, not one-to-oneVariant->net.minecraft.client.renderer.block.model.Variant, not one-to-oneVariantProperties->net.minecraft.client.renderer.block.model.VariantMutator, not one-to-oneVariantProperty->net.minecraft.client.renderer.block.model.VariantMutator$VariantProperty, not one-to-one
net.minecraft.client.renderer.ItemInHandRenderer#renderItemno longer takes in the boolean representing if the item is held in the left handnet.minecraft.client.renderer.blockBlockModelShaper#stateToModelLocation,statePropertiesToStringis removedBlockRenderDispatcher#renderBatchednow takes in a list ofBlockModelParts instead of aRandomSourceModelBlockRenderertesselateBlock,tesselateWithAO,tesselateWithoutAOno longer takes in aRandomSourceand replacesBlockStateModelwith a list ofBlockModelPartsrenderModelis now static and no longer takes in theBlockState$AmbientOcclusionFace->$AmbientOcclusionRenderStorage$CommonRenderStorage- A class that holds some metadata used to render a block at its given position.$SizeInfonow takes in the direct index rather than computing the info from its direction and a flipped boolean
net.minecraft.client.renderer.block.modelBakedQuadis now a recordBlockElementis now a recordfrom,toare nowVector3fc
BlockElementFacenow takes in aQuadrantfor the face rotationgetU,getV- Returns the texture coordinate after rotation.$Deserializer#getTintIndexis now private and static
BlockFaceUV->BlockElementFace$UVs, not one-to-oneBlockModelis now a record, taking in anUnbakedGeometryinstead of the direct list ofBlockElements$Deserializer#getElementsnow returns anUnbakedGeometry
BlockModelDefinitionis now a record, taking in$SimpleModelSelectorsand$MultiPartDefinitionsGSON,fromStream,fromJsonElement->CODEC, not one-to-oneinstantiatenow takes in a supplied string instead of the string directly$Deserializeris removed$MultiPartDefinition- A record that holds a list of selectors to get for the multi part model.$SimpleModelSelectors- A record that holds a map of variants to their unbaked model instances.
BlockModelPart- A baked model representation of a block.BlockStateModel- A baked representation of a block state.collectParts- Obtains the list of baked models used to render this state.$SimpleCachedUnbakedRoot- A class that represents a delegate of some$Unbakedmodel.$Unbaked- An extension over$UnbakedRootthat can create a$SimpleCachedUnbakedRoot
FaceBakerybakeQuadnow takes inVector3fcs instead ofVector3fsrecomputeUVsis removedextractPositions- Extracts the face positions and passes them to a consumer for use.
ItemTransformis now a record, vectors areVector3fcsMultiVariant->net.minecraft.client.data.models.MultiVariantCODECwith- Creates aMultiVariantwith the specified mutators.$Deserializerclass is removed
SimpleModelWrappernow implementsBlockModelPartSimpleUnbakedGeometry- An unbaked geometry that holds a list ofBlockElements to bake.SingleVariant- ABlockStateModelimplementation with only one model for its state.UnbakedBlockStateModel->BlockStateModel$UnbakedRootVariantno longer implementsModelState, now taking in a$SimpleModelStateinstead of the direct rotation and uv lock- The constructor now has an overload for only providing the
ResourceLocationand no longer takes in the weight, leaving that to theMultiVariant CODECwithXRot,withYRot,withUvLock,withModel,withState,with- Mutates the variant into a new object with the given setting applied.$Deserializerclass is removed$SimpleModelState- A record that holds the x/y rotations and uv lock.
- The constructor now has an overload for only providing the
VariantMutator- A unary operator on a variant that applies the specified setting to the variant. Used during state generation.
net.minecraft.client.renderer.block.model.multipartAndCondition,OrCondition->CombinedCondition, not one-to-oneKeyValueConditionis now a record that takes in a map of keys to terms to testMultiPart->MultiPartModel$Unbaked$DefinitionCODECgetMultiVariantsis removed
$Deserializerclass is removed
Selectoris now a record, taking in aBlockStateModel$Unbakedinstead of aMultiVariant$Deserializerclass is removed
net.minecraft.client.renderer.entity.ItemRendererrenderItemnow takes in aList<BakedQuad>instead of aBakedModelrenderStaticno longer takes in a boolean indicating what hand the item was held in
net.minecraft.client.renderer.itemBlockModelWrappernow has a public constructor that takes in the list of tint sources, the list of quads, and theModelRenderProperties- The list of quads and
ModelRenderPropertiesreplaces the directBakedModel, or nowBlockStateModel computeExtents- Extracts the vertices of the baked quads into an array.
- The list of quads and
ItemModel$BakingContext#bakeis removedItemModelResolver#updateForLiving,updateForTopItemno longer takes in a boolean representing if the item is in the left handItemStackReenderStateisGui3dis removedtransformis removedvisitExtents- Visits all vertices of the model to render and passes them into the provided consumer.$LayerRenderStateNO_EXTENTS_SUPPLIER- An empty list of vertices.setupBlockModelhas been broken intoprepareQuadList,setRenderType,setUsesBlockLight,setExtents,setParticleIcon,setTransformsetupSpecialModelno longer takes in the baseBakedModel
MissingItemModelnow takes in a list ofBakedQuads andModelRenderPropertiesinstead of the directBakedModelModelRenderProperties- The properties used to render a model, typically retrieved from theResolvedModel.SpecialModelRenderernow takes in theModelRenderPropertiesinsetad of the baseBakedModel
net.minecraft.client.resources.modelBakedModel->net.minecraft.client.resources.model.QuadCollection, not one-to-oneBlockModelRotationbynow takes inQuadrants instead of integerswithUvLock- Returns the model state with the rotation and a mention that it locks the UV for the rotation.
BlockStateDefinitions- A manager for creating the mapper of block names to their state defintions.BlockStateModelLoaderModelResourceLocationfields are removedloadBlockStateno longer takes in the missing model$LoadedModelclass is removed$LoadedModelsnow takes in aBlockStateModel$UnbakedRootinstead of an$UnbakedforResolving,plainModelsis removed
DelegateBakedModel->net.minecraft.client.renderer.block.model.SimpleModelWrapper, not one-to-oneMissingBlockModel#VARIANTis removedModelBakerbake->getModel, not one-to-one- The baker is simply retrieving the
ResolvedModel
- The baker is simply retrieving the
rootNameis removedcompute- Computes the provided key that contains theModelBaker. Typically used for bakingBlockStateModels$SharedOperationKey- An interface which typically computes some baking process for an unbaked model.
ModelBakerynow takes in aMap<BlockState, BlockStateModel$UnbakedRoot>for the unbaked block state models, aMap<ResourceLocation, ResolvedModel>for the loaded models, and aResolvedModelfor the missing modelbakeModelsnow takes in aSpriteGetterand anExecutorwhile returning aCompletableFuturefor parallel loading and baking$BakingResultnow takes in a$MissingModelsfor the missing block state and item model and aMap<BlockState, BlockStateModel>for the baked block state models; the missing item model is stored within$MissingModels$MissingModels- Holds the missing models for a block state and item.$TextureGetterinterface is removed
ModelDebugNameno longer extendsSupplier<String>, instead usingdebugNameModelDiscoveryregisterSpecialModelsis removeddiscoverDependenciesis now privategetReferencedModels,getUnreferencedModelsis removedaddSpecialModel- Adds a root model to the list of arbitrarily loaded models.missingModel- Returns the missing modelresolve- Resolves all model dependencies, returning a map of model names to their models.
ModelGroupCollector$GroupKey#createnow takes in aBlockStateModel$UnbakedRootinstead of an$UnbakedModelManagergetModelis removedgetMissingModel->getMissingBlockStateModel$ResolvedModels- A map of models with their dependencies resolved.
ModelResourceLocationrecord is removedModelStategetRotation->transformationisUvLockedis removedfaceTransfomration,inverseFaceTransformation- Handles returning the transformedMatrix4fcfor baking the face vertices.
MultiPartBakedModel->net.minecraft.client.renderer.block.model.multipart.MultiPartModel- Now implements
BlockStateModelinstead of extendingDelegateBakedModel $SharedBlockState- A holder that contains theBlockStateModels mapped to their$Selectors.
- Now implements
QuadCollection- A data object containing the list of quads to render based on the associated direction and culling.ResolvableModel$Resolver#resolve->markDependency, not one-to-one- Instead of directly resolving, the dependency is marked for a later post processing step
ResolvedModel- AnUnbakedModelwhose model and texture dependencies have been completely resolved.SimpleBakedModel->net.minecraft.client.renderer.block.model.SimpleModelWrapperornet.minecraft.client.renderer.block.model.SimpleUnbakedGeometry, not one-to-oneSpriteGetterget,reportMissingReferencenow take in theModelDebugNameresolveSlot- Resolves the key from theTextureSlots into itsTextureAtlasSprite.
UnbakedGeometry- An interface that constructs a collection of quads the render when baked.UnbakedModelno longer implementsResolvableModelDEFAULT_AMBIENT_OCCLUSION,DEFAULT_GUI_LIGHTis removedPARTICLE_TEXTURE_REFERENCE- Holds the key representing the particle texture.bakeis removedgetAmbientOcclusion->ambientOcclusiongetGuiLight->guiLightgetTransforms-transformsgetTextureSlots-textureSlotsgeometry- Holds the unbaked geometry representing the model elements.getParent->parent, not one-to-onebakeWithTopModelValuesis removedgetTopTextureSlots,getTopAmbientOcclusion,getTopGuiLight,getTopTransform,getTopTransformsis removed
WeightedBakedModel->WeightedVariants- Now implements
BlockStateModelinstead of extendingDelegateBakedModel
- Now implements
net.minecraft.world.item.ItemDisplayContext#leftHand- Returns whether the display context is rendering with the entity's left hand.
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.
Entity References
Generally, the point of storing the UUID of another entity was to later grab that entity to perform some logic. However, storing the raw entity could lead to issues if the entity was removed at some point in time. As such, the EntityReference was added to handle resolving the entity from its UUID while also making sure it still existed at the time of query.
An EntityReference is simply a wrapped Either which either holds the entity instance or the UUID. When resolving via getEntity, it will attempt to verify that the stored entity, when present, isn't removed. If it is, it grabs the UUID to perform another lookup for the entity itself. If that entity does exist, it will be return, or otherwise null.
Most references to a UUID within an entity have been replaced with an EntityReference to facilitate this change.
net.minecraft.network.syncher.EntityDataSerializers#OPTIONAL_UUID->OPTIONAL_LIVING_ENTITY_REFERENCE, not one to one as it can hold the entity referencenet.minecraft.server.level.ServerLevel#getEntity(UUID)->Level#getEntity(UUID)net.minecraft.world.entityEntityReference- A reference to an entity either by its entity instance when present in the world, or a UUID.LivingEntity#lastHurtByPlayer,lastHurtByMobare nowEntityReferencesOwnableEntitygetOwnerUUID->getOwnerReference, not one-to-onelevelnow returns aLevelinstead of anEntityGetter
TamableAnimal#setOwnerUUID->setOwner, orsetOwnerReference; not one-to-one
net.minecraft.world.entity.animal.horse.AbstractHorse#setOwnerUUID->setOwner, not one-to-onenet.minecraft.world.level.Levelnow implementsUUIDLookup<Entity>net.minecraft.world.level.entityEntityAccessnow implementsUniquelyIdentifyableUniquelyIdentifyable- An interface that claims the object as a UUID and keeps tracks of whether the object is removed or not.UUIDLookup- An interface that looks up a type by its UUID.
Descoping Player Arguments
Many methods that take in the Player has been descoped to take in a LivingEntity or Entity depending on the usecase. The following methods below are a non-exhaustive list of this.
net.minecraft.world.entity.EntityTypespawncreateDefaultStackConfig,appendDefaultStackConfigappendCustomEntityStackConfig,updateCustomEntityTag
net.minecraft.world.itemBucketItem#playEmptySoundDispensibleContainerItem#checkExtraContent,emptyContents
net.minecraft.world.levelLevelplaySeededSoundmayInteract
LevelAccessorplaySoundlevelEvent
net.minecraft.world.level.blockBucketPickup#pickupBlockLiquidBlockContainer#canPlaceLiquid
net.minecraft.world.level.block.entity.BrushableBlockEntity#brush
Component Interaction Events
Click and hover events on a MutableComponent have been reworked into MapCodec registry-like system. They are both now interfaces that register their codecs to an $Action enum. The implementation then creates a codec that references the $Action type and stores any necessary information that is needed for the logic to apply. However, there is no direct 'action' logic associated with the component interactions. Instead, they are hardcoded into their use locations. For click events, this is within Screen#handleComponentClicked. For hover events, this is in GuiGraphics#renderComponentHoverEffect. As such, any additional events added will need to inject into both the enum and one or both of these locations.
net.minecraft.network.chatClickEventis now an interfacegetAction->actiongetValueis now on the subclasses as necessary for their individual types
HoverEventis now an interfacegetAction->action$EntityTooltipInfoCODECis now aMapCodeclegacyCreateis removed
$ItemStackInfois removed, replaced by$ShowItem$LegacyConverterinterface is removed
Texture Atlas Reworks
The texture atlas logic has been finalized into a registry codec system; however, the querying of the atlas data has changed. First, all atlas identifiers are stored within AtlasIds while the corresponding texture location is stored within Sheets. To get a material from an atlas, a MaterialMapper is used as a wrapper around the texture location and the associated prefix to append to the material. The Material can then be obtained using apply by passing in the id of the material you would like to use.
For example:
// Found in sheets
public static final MaterialMapper ITEMS_MAPPER = new MaterialMapper(TextureAtlas.LOCATION_BLOCKS, "item");
public static final MaterialMapper BLOCKS_MAPPER = new MaterialMapper(TextureAtlas.LOCATION_BLOCKS, "block");
// Finds the texture for the material at `assets/examplemod/textures/item/example_item.png`
public static final Material EXAMPLE_ITEM = ITEMS_MAPPER.apply(ResourceLocation.fromNamespaceAndPath("examplemod", "example_item"));
// Finds the texture for the material at `assets/examplemod/textures/block/example/block.png`
public static final Material EXAMPLE_BLOCK = ITEMS_MAPPER.apply(ResourceLocation.fromNamespaceAndPath("examplemod", "example/block"));
net.minecraft.client.data.AtlasProvider- A data provider for generating the providers of a texture atlas.net.minecraft.client.data.models.ItemModelGeneratorsSLOT_*->TRIM_PREFIX_*, now public andResourceLocationsTRIM_MATERIAL_MODELSis now publicgenerateTrimmableItemnow takes in aResourceLocationinstead of aString$TrimMaterialDatais now public, taking in aMaterialAssetGroupinstead of the name and override materials
net.minecraft.client.rendererMaterialMapper- An object that stores the location of the atlas texture and the prefix applied to the ids within the texture.Sheets*_MAPPER-MaterialMappers for each texture atlas texture.createBedMaterial(ResourceLocation)is removedcreateShulkerMaterial(ResourceLocation)is removedcreateSignMaterial(ResourceLocation)is removedchestMaterial(String),chestMaterial(ResourceLocation)are removedcreateDecoratedPotMaterial(ResourceLocation)is removed
net.minecraft.client.renderer.blockentity.ConduitRenderer#MAPPER- A mapper to get the conduit textures from the block atlas.net.minecraft.client.renderer.texture.atlasSpriteSource#type->codec, not one-to-oneSpriteSourcesnow contains logic similar to client registries via their id mapperSpriteSourceTyperecord is removed
net.minecraft.client.renderer.texture.atlas.sourcesDirectoryListeris now a recordPalettedPermutationsis now a recordSingleFileis now a recordSourceFilteris now a recordUnstitcheris now a record$Regionis now public
net.minecraft.client.resources.model.AtlasIds- A class which holds theResourceLocations of all vanilla texture atlases.
Registry Context Swapper
Client items now store a RegistryContextSwapper, which is used to properly check client item information that accesses registry objects. Before level load, this is provided a placeholder to avoid crashing and populated with the correct value during rendering.
net.minecraft.client.multiplayerCacheSlot- An object that contains a value computed from some context. When updated, the previous value is overwritten and the context registers the slot to be cleaned.ClientLevelnow implementsCacheSlot$Cleaner
net.minecraft.client.renderer.itemClientItemcan now take in a nullableRegistryContextSwapperwithRegistrySwapper- Sets theRegistryContextSwapperwithin aClientItem
ItemModel$BakingContextnow takes in aRegistryContextSwapper
net.minecraft.utilPlaceholderLookupProvider- A provider that contains placeholders for referenced objects. Used within client items as they will be loaded before theRegistyAccessis populated.RegistryContextSwapper- An interface used to swap out some object for a different one. Used by client items to swap the placeholders for the loadedRegistryAccess.
Reload Instance Creation
Reload instances have been slightly rearranged. The SimpleReloadInstance base now only takes in the List<PreparableReloadListener>, where the other fields are passed into the of function such that #startTasks can be called immediately.
net.minecraft.server.packs.resourcesProfiledReloadInstanceconstruct is now private, accessed throughofSimpleReloadInstanceonly takes in theList<PreparableReloadListener>ofnow returns aReloadInstance, not one-to-oneallPreparationsis now package privateallDoneis now privatestartTasks- Begins the reload of the listener.prepareTasks- Runs the executor and sets up the futures needed to read and load all desired data.StateFactory$SIMPLE- A factory that callsPreparableReloadListener#reload
Block Effect Appliers
Effects that are applied to entities when inside a block are now handled through the InsideBlockEffectApplier and InsideBlockEffectType. The InsideBlockEffectType is an enum that contains a consumer on what to apply to an entity when called. InsideBlockEffectApplier, on the other hand, is stored on the entity has a way to apply an effect in a ordered manner based on the enum ordinals.
To call one of the effect types, you must override BlockBehaviour#entityInside or Fluid#entityInside and call InsideBlockEffectApplier#apply. If something should apply before the effect type, like entinguishing fire before freezing in powder snow, then InsideBlockEffectApplier#runBefore should be called before apply. Similarly, if something should run afterward, like hurting an enemy after being placed in lava, then runAfter should be called.
// In some block or fluid subclass
@Override
protected void entityInside(Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier applier) {
applier.runBefore(InsideBlockEffectType.EXTINGUISH, entity -> {
// Modify entity here.
});
// Do the base application logic stored on the type
applier.apply(InsideBlockEffectType.FIRE_IGNITE);
applier.runAfter(InsideBlockEffectType.FIRE_IGNITE, entity -> {
// Perform any final checks that are as a result of the effect being applied
entity.hurt(...);
});
}
net.minecraft.world.entityInsideBlockEffectApplier- An interface that defines how an entity should interact when within a given block.InsideBlockEffectType- An enum that defines what behavior to perform when side the specific block that references the type.
net.minecraft.world.level.block.state.BlockBehaviour#entityInside,$BlockStateBase#entityInsidenow takes in anInsideBlockEffectAppliernet.minecraft.world.level.material.Fluid#entityInside,FluidState#entityInside- A method called whenever the entity is considered inside the bounding box of the fluid.
Timer Callbacks, joining the codec club!
TimerCallbacks, used in the server schedule for executing events, typically mcfunctions in datapacks, have now been reworked into a codec form. This means that a callback can be registered to the list of available callbacks by passing in the MapCodec to TimerCallbacks#register (via TimerCallbacks#SERVER_CALLBACKS) instead of the serializer.
net.minecraft.world.level.timersFunctionCallbackis now a recordFunctionTagCallbackis now a recordTimerCallbackcodec- Returns the codec used for serialization.$Serializerclass is removed
TimerCallbacksserialize,deserialize->codec, not one-to-one
The JOML Backing Interfaces
Mojang has opted to lessen the restriction on JOML objects by passing around the implementing interface of their logic objects (usually implemented with a tacked on c). For example, Vector3f becomes Vector3fc or Matrix4f becomes Matrix4fc. This does not change any logic itself as the c interfaces are implemented by the class components.
Tag Changes
minecraft:worldgen/biomespawns_cold_variant_farm_animalsspawns_warm_variant_farm_animals
minecraft:blocksword_instantly_minesreplaceable_by_mushroomsplays_ambient_desert_block_soundsedible_for_sheepdead_bush_may_place_on->dry_vegetation_may_place_oncamels_spawnable_on
minecraft:cat_variantare removedminecraft:entity_typecan_equip_saddlecan_wear_horse_armor
minecraft:itembook_cloning_targeteggsflowers
Mob Effects Field Renames
Some mob effects have been renamed to their in-game name, rather than some internal descriptor.
MOVEMENT_SPEED->SPEEDMOVEMENT_SLOWDOWN->SLOWNESSDIG_SPEED->HASTEDIG_SLOWDOWN->MINING_FATIGUEDAMAGE_BOOST->STRENGTHHEAL->INSTANT_HEALTHHARM->INSTANT_DAMAGEJUMP->JUMP_BOOSTCONFUSION->NAUSEADAMAGE_RESISTANCE->RESISTANCE
Very Technical Changes
This is a list of technical changes that could cause highly specific errors depending on your specific setup.
-
The order of the
minecraft:patch_sugar_canefeature andminecraft:patch_pumpkinfeature have swapped orders (first pumpkin, then sugar cane), meaning modded biomes that generate both of these features will need to update their JSONs to the new ordering. -
Serveral vanilla oak tree and tree selector features now have
_leaf_litterappended at the end.- For example:
trees_birch_and_oak->trees_birch_and_oak_leaf_litter
- For example:
List of Additions
net.minecraftChatFormatting#COLOR_CODECCrashReportCategory#populateBlockLocationDetails- Adds the block location details to a crash report.
net.minecraft.advancements.critereon.MinMaxBounds#createStreamCodec- Constructs a stream codec for aMinMaxBoundsimplementation.net.minecraft.client.Options#startedCleanly- Sets whether the game started cleanly on last startup.net.minecraft.client.data.modelsBlockModelGenerators#createSegmentedBlock- Generates a multipart blockstate definition with horizontal rotation that displays up to four models based on some integer property.ItemModelGenerators#prefixForSlotTrim- Generates a vanillaResourceLocationfor a trim in some slot.
net.minecraft.client.MouseHandlerfillMousePositionDetails- Adds details about the current mouse location and screen size to a crash report.getScaledXPos- Gets the current x position scaled by the gui scaling option.getScaledYPos- Gets the current y position scaled by the gui scaling option.drawDebugMouseInfo- Draws information about the scaled position of the mouse to the screen.
net.minecraft.client.gui.components.toasts.Toast#getSoundEvent- Returns the sound to play when the toast is displayed.net.minecraft.client.gui.screens.options.VideoSettingsScreen#updateFullscreenButton- Sets the fullscreen option to the specified boolean.net.minecraft.client.model.geom.buildersMeshDefinition#apply- Applies the given transformer to the mesh before returning a new instance.MeshTransformer#IDENTITY- Performs the identity transformation.
net.minecraft.client.multiplayer.ClientPacketListener#decoratedHashOpsGenenerator- Returns the generator used to create a hash of a data component and its value.net.minecraft.client.particleFallingLeavesParticle$TintedLeavesProvider- A provider for aFallingLeavesParticlethat uses the color specified by the block above the particle the spawn location.FireflyParticle- A particle that spawns fireflies around a given non-air block position.
net.minecraft.client.rendererBiomeColors#getAverageDryFoliageColor- Returns the average foliage color for dry biomes.LevelRenderer$BrightnessGetter- An interfaces which obtains the packed brightness at a given block position.WorldBorderRenderer#invalidate- Invalidates the current render of the world border to be rerendered.
net.minecraft.client.renderer.entityEntityRenderDispatcher#getRenderer- Gets the renderer to use from the data stored on the render state.EntityRenderer#extractAdditionalHitboxes- Gets any additional hitboxes to render when the 'show hitboxes' debug state is enabled.
net.minecraft.client.renderer.entity.stateEntityRenderStateentityType- The type of the entity.hitboxesRenderState- The hitbox information of the entity relative to the entity's position.serverHitboxesRenderState- The hitbox information of the entity synced from the server.fillCrashReportCategory- Sets the details for any crashes related to the render state.
HitboxesRenderState- The render state of the hitboxes for the entity relative to the entity's position.HitboxRenderState- The render state of a single hitbox to render along with its color, such as the eye height of an entity.ServerHitboxesRenderState- The render state containing the last synced information from the related server entity.PigRenderState#variant- The variant of the pig.
net.minecraft.client.renderer.item.SelectItemModel$ModelSelector- A functional interface that selects the item model based on the switch case and level.net.minecraft.client.renderer.item.properties.conditional.ComponentMatches- A conditional property that checks whether the given predicate matches the component data.net.minecraft.client.renderer.item.properties.selectComponentContents- A switch case property that operates on the contents within a data component.SelectItemModelProperty#valueCodec- Returns theCodecfor the property type.
net.minecraft.client.resources.DryFoliageColorReloadListener- A reload listener that loads the colormap for dry foliage.net.minecraft.commands.arguments.ComponentArgument#getResolvedComponent- Constructs a component with the resolved information of its contents.net.minecraft.coreDirection#getUnitVec3f- Returns the float unit vector of the direction.HolderGetter$Provider#getOrThrow- Gets a holder reference from a resource key.SectionPos#sectionToChunk- Converts a compressed section position to a compressed chunk position.Vec3i#STREAM_CODEC
net.minecraft.networkHashedPatchMap- A record containing a map of components to their hashed type/value along with a set of removed components.HashedStack- AnItemStackrepresentation that hashes the stored components.ProtocolInfo$DetailsProvider- Provides the details for a given protocol.SkipPacketDecoderException- An exception thrown when an error occurs during decoding before having its data ignored.SkipPacketEncoderException- An exception thrown when an error occurs during encoding before having its data ignored.
net.minecraft.network.chatLastSeenMessagescomputeChecksum- Computes a byte representing the merged checksums of all message signatures.$Update#verifyChecksum- Verifies that the update checksum matches those within the last seen messages.
LastSeenMessagesValidator$ValidationException- An exception thrown if the messages can not be validated.MessageSignaturedescribe- Returns a stringified version of the message signature.checksum- Hashes the bytes within the signature into a single integer.
PlayerChatMessage#describeSigned- Returns a stringified version of the chat message.
net.minecraft.network.codecByteBufCodecsLONG_ARRAYlengthPrefixed- Returns an operation that limits the size of the buffer to the given size.
IdDispatchCodec$DontDecorateException- An interface that tells the exception handler to rethrow the raw exception rather than wrap it within anEncoderException.
net.minecraft.network.protocolCodecModifier- A function that modifies some codec using a given object.ProtocolInfoBuilder#context*Protocol- Builds anUnboundProtocolwith the given context used to modify the codecs to send.
net.minecraft.network.protocol.game.GameProtocolsHAS_INFINITE_MATERIALS- A modifier that checks theServerboundSetCreativeModeSlotPacketfor if the player has the necessary settings. If not, the packet is discarded.$Context- Returns the context used by the packet to modify the incoming codec.
net.minecraft.resources.DelegatingOps$DelegateListBuilder- A list builder that can be subclassed if needed.$DelegateRecordBuilder- A record builder that can be subclassed if needed.
net.minecraft.server.bossevents.CustomBossEvent$Packed- A record that backs the event information for serialization.net.minecraft.server.commands.InCommandFunction- A command function that takes in some input and returns a result.net.minecraft.server.levelDistanceManager#forEachBlockTickingChucnks- Applies the provided consumer for each chunk with block ticking enabled.ServerLevelareEntitiesActuallyLoadedAndTicking- Returns whether the entity manager is actually ticking and loading entities in the given chunk.tickThunder- Ticks the thunger logic within a given level.anyPlayerCloseEnoughForSpawning- Returns if a player is close enough to spawn the entity at the given location.
ServerPlayer$RespawnConfig- A record containing the respawn information for the player.
net.minecraft.utilAbstractListBuilder- A ops list builder which boils the implementation down to three methods which initializes, appends, and builds the final list.Brightnessblock- Returns the block light from a packed value.sky- Returns the sky light from a packed value.
HashOps- A dynamic ops that generates a hashcode for the data.ExtraCodecsUNTRUSTED_URI- A codec for a URI that is not trusted by the game.CHAT_STRING- A codec for a string in a chat message.legacyEnum- A codec that maps an enum to its output inEnum#toString.
FileSystemUtil- A utility for interacting with the file system.GsonHelper#encodesLongerThan- Returns whether the provided element can be written in the specified number of characters.Unit#STREAM_CODEC- A stream codec for a unit instance.UtilmapValues- Updates the values of a map with the given function.mapValuesLazy- Updates the values of a map with the given function, but each value is resolved when first accessed.growByHalf- Returns an integer multiplied by 1.5, rounding down, clamping the value to some minimum and the max integer size.
net.minecraft.util.random.Weighted#map,WeightedList#map- Transforms the stored object(s) to a new type.net.minecraft.util.thread.ParallelMapTransform- A helper that handles scheduling and batching tasks in parallel.net.minecraft.world.effect.MobEffectInstance#withScaledDuration- Constructs a new instance with the duration scaled by some float value.net.minecraft.world.entityAreaEffectCloud#setPotionDurationScale- Sets the scale of how long the potion should apply for.DropChances- A map of slots to probabilities indicating how likely it is for an entity to drop that piece of equipment.EntityisInterpolating- Returns whether the entity is interpolating between two steps.sendBubbleColumnParticles- Spawns bubble column particles from the server.canSimulateMovement- Whether the entity's movement can be simulated, usually from being the player.propagateFallToPassengers- Propogates the fall damage of a vehicle to its passengers.lavaIgnite- Ignites the entity for 15 seconds if not immune.clearFreeze- Sets the number of ticks the entity is frozen for to 0.removeLatestMovementRecordingBatch- Removes the last element from all movements performed this tick.
InterpolationHandler- A class meant to easily handle the interpolation of the position and rotation of the given entity as necessary.LivingEntitygetLuck- Returns the luck of the entity for random events.getLastHurtByPlayer,setLastHurtByPlayer- Handles the last player to hurt this entity.getEffectBlendFactor- Gets the blend factor of an applied mob effect.applyInput- Applies the entity's input as its AI, typically for local players.INPUT_FRICTION- The scalar to apply to the movements of the entity.
net.minecraft.world.entity.animal.camel.Camel#checkCamelSpawnRules- Checks if a camel can spawn at a particular position.net.minecraft.world.entity.animal.sheep.SheepColorSpawnRules- A class that contains the color spawn configurations for a sheep's wool when spawning within a given climate.net.minecraft.world.entity.npc.Villager#createDefaultVillagerData- Returns the default type and profession of the villager to use when no data is set.net.minecraft.world.entity.player.PlayerpreventsBlockDrops- Whether the player cannot drop any blocks on destruction.gameMode- Returns the current game mode of the player.debugInfo- Returns the common information about the player as a single string.
net.minecraft.world.inventoryContainerSynchronizer#createSlot- Creates aRemoteSlotthat represents a slot on the opposite side.RemoteSlot- A slot that represents the data on the opposing side, syncing when the data is not consistent.
net.minecraft.world.itemEitherHolder#key- Returns the resource key of the held registry object.Item#STREAM_CODECItemStackOPTIONAL_UNTRUSTED_STREAM_CODECMAP_CODECcanDestroyBlock- Returns whether this item can destroy the provided block state.
net.minecraft.world.item.alchemy.PotionContents#getPotionDescription- Returns the description of the mob effect with some amplifier.net.minecraft.world.item.craftingRecipe#KEY_CODECTransmuteResult- A recipe result object that represents an item, count, and the applied components.
net.minecraft.world.item.equipment.trim.ArmorTrim#layerAssetId- Returns the location of the the trim asset.net.minecraft.world.levelBlockGetter$BlockStepVisitor- A consumer that takes in the current position and how many collisions within the desired path of travel.ColorMapColorUtil- A helper for getting the color from a map given the biome's temperature, downfall, colormap, and default color.DryFoliageColor- A color resolver for biomes with dry foliage.GameRulesgetType- Gets the game rule type from its key.keyCodec- Creates the codec for the key of a game rule type.
LevelisMoonVisible- Returns wehther the moon is currently visible in the sky.getPushableEntities- Gets all entities except the specified target within the provided bounding box.getClientLeafTintColor- Returns the color of the leaf tint at the specified location.playPlayerSound- Plays a sound to the current player on the client.
LevelReader#getHeight- Returns the height of the map at the given position.NaturalSpawner#INSCRIBED_SQUARE_SPAWN_DISTANCE_CHUNK- Provides the minimum distance that the player is close enough for spawning to occur.
net.minecraft.world.level.biomeBiomegetDryFoliageColor,getDryFoliageColorFromTexture- Gets the dry foliage color of the biome, either from the effects or from the climate settings.
BiomeSpecialEffects#getDryFoliageColorOverride,$Builder#dryFoliageColorOverride- Returns the default dry foliage color when not pulling from a colormap texture.
net.minecraft.world.level.blockBaseFireBlock#fireIgnite- Lights an entity on fire.BlockUPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS- A flag that skips all potential sideeffects when updating a block entity.UPDATE_SKIP_ALL_SIDEEFFECTS- A flag that skips all sideeffects by skipping certain block entity logic, supressing drops, and updating the known shape.UPDATE_SKIP_ON_PLACE- A flag that skips callingBlockState#onPlacewhen set.
BonemealableBlock#hasSpreadableNeighbourPos,findSpreadableNeighbourPos- Handles finding other positions that the vegetation can spread to on bonemeal.CactusFlowerBlock- A flower that grows on a cactus.FireflyBushBlock- A bush that spawns firefly particles around it.SandBlock- A colored sand block that can play ambient sounds.SegmentableBlock- A block that can typically be broken up into segments with unique sizes and placements.ShortDryGrassBlock- A single grass block that has been dried out.TallDryGrassBlock- A double grass block that has been dried out.TerracottaBlock- A terracotta block that can play ambient sounds.TintParticleLeavesBlock- A leaves block whose particles are tinted.UntintedParticleLeavesBlock- A leaves block whose particles are not tinted.VegetationBlock- A block that represents some sort of vegetation that can propogate light and need some sort of farmland or dirt to survive.
net.minecraft.world.level.block.entity.StructureBlockEntity#isStrict,setStrict- Sets strict mode when generating structures.net.minecraft.world.level.block.sounds.AmbientDesertBlockSoundsPlayer- A helper to play sounds for a given block, typically duringanimateTick.net.minecraft.world.level.block.state.BlockBehaviour#getEntityInsideCollisionShape- Gets the collision shape of the block when the entity is within it.net.minecraft.world.level.border.WorldBorderclosestBorder- Returns a list of the closest borders to the player based on their horizontal direction.$DistancePerDirection- A record containing the distance from the entity of the world border in a given direction.
net.minecraft.world.level.chunk.status.ChunkStatus#CODECnet.minecraft.world.level.entity.PersistentEntitySectionManager#isTicking- Returns whether the specified chunk is currently ticking.net.minecraft.world.level.levelgen.Heightmap$Types#STREAM_CODECnet.minecraft.world.level.levelgen.featureAbstractHugeMushroomFeature#placeMushroomBlock- Places a mushroom block that specified location, replacing a block if it can.FallenTreeFeature- A feature that generates flane trees with a stump of given lengths.TreeFeature#getLowestTrunkOrRootOfTree- Retruns the lowest block positions of the tree decorator.
net.minecraft.world.level.levelgen.feature.configurations.FallenTreeConfiguration- A configuration for fallen trees with stumps.net.minecraft.world.level.levelgen.feature.treedecoratorsAttachedToLogsDecorator- A decorator that attaches a random block to a given direction on a log with a set probability.PlaceOnGroundDecorator- A decorator that places the tree on a valid block position.
net.minecraft.world.level.levelgen.structure.poolsListPoolElement#getElements- Returns the elements of the structure pool.SinglePoolElement#getTemplateLocation- Returns the location of the template used by the element.StructureTemplatePool#getTemplates- Returns a list of elements with their weights.
net.minecraft.world.level.levelgen.structure.structures.JigsawStructuregetStartPool- Returns the starting pool of the jigsaw to generate.getPoolAliases- Returns all pools used by the jigsaw.
net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate#getDefaultJointType- Returns the default join type between two jigsaw pieces if none is specified or an error occurs during loading.net.minecraft.world.level.material.Fluid#getAABB,FluidState#getAABB- Returns the bounding box of the fluid.net.minecraft.world.scoresObjective#pack,$Packed- Handles the serializable form of the objective data.PlayerTeam#pack,$Packed- Handles the serializable form of the player team data.ScoreboardloadPlayerTeam,loadObjective- Loads the data from the packed object.$PackedScore- Handles the serializable form of the scoreboard data.
net.minecraft.world.level.storage.loot.LootTable#KEY_CODECnet.minecraft.world.physAABB$Builder- A builder for constructing a bounding box by providing the vectors within.Vec2#CODEC
net.minecraft.world.phys.shapes.CollisionContextplacementContext- Constructs the context when placing a block from its item.isPlacement- Returns whether the context is being used for placing a block.
net.minecraft.world.ticks.TickPriority#CODEC
List of Changes
net.minecraft.client.Screenshotis now a utility instead of an instance class, meaning all instance methods are removedtakeScreenshot(RenderTarget)->takeScreenshot(RenderTarget, Consumer<NativeImage>), not returning anything
net.minecraft.client.multiplayerClientChunkCache#replaceWithPacketDatanow takes in aMap<Heightmap$Types, long[]>instead of aCompoundTagMultiPlayerGameMode#hasInfiniteItems->net.minecraft.world.entity.LivingEntity#hasInfiniteMaterialsClientPacketListener#markMessageAsProcessednow takes in aMessageSignatureinstead of aPlayerChatMessage
net.minecraft.client.multiplayer.chat.ChatListener#handleChatMessageErrornow takes in a nullableMessageSignaturenet.minecraft.client.playerClientInput#leftImpulse,forwardImpulse->moveVector, now protectedLocalPlayer#spinningEffectIntensity,oSpinningEffectIntensity->portalEffectIntensity,oPortalEffectIntensity
net.minecraft.client.renderer.LevelRenderer#getLightColor(BlockAndTintGetter, BlockState, BlockPos)->getLightColor(LevelRenderer$BrightnessGetter, BlockAndTintGetter, BlockState, BlockPos)net.minecraft.client.renderer.blockentity.BlockEntityRenderer#rendernow takes in aVec3representing the camera's positionnet.minecraft.client.renderer.chunk.SectionRenderDispatcher$RenderSectiongetOrigin->getRenderOriginresetis now publicreleaseBuffersis removed
$CompileTask#getOrigin->getRenderOrigin
net.minecraft.client.renderer.entityDonkeyRenderernow takes in aDonekyRenderer$Typecontaining the textures, model layers, and equipment informationItemEntityRenderer#renderMultipleFromCountnow has an overload that takes in the model bounding boxUndeadHorseRenderernow takes in aUndeadHorseRenderer$Typecontaining the textures, model layers, and equipment information
net.minecraft.client.renderer.entity.layersEquipmentLayerRenderer$TrimSpriteKey#textureId->spriteIdVillagerProfessionLayer#getHatDatanow takes in a map of resource keys to metadata sections and swaps the registry and value for a holder instance
net.minecraft.client.renderer.itemConditionalItemModelnow takes in aItemModelPropertyTestinstead of aConditionalItemModelPropertySelectItemModelnow takes in a$ModelSelectorinstead of an object map
net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelPropertynow implementsItemModelPropertyTestItemModelPropertyTestholds thegetmethod previously withinConditionalItemModelProperty
net.minecraft.commands.argumentsComponentArgumentERROR_INVALID_JSON->ERROR_INVALID_COMPONENTgetComponent->getRawComponent
ResourceKeyArgument#getRegistryKeyis now publicStyleArgument#ERROR_INVALID_JSON->ERROR_INVALID_STYLE
net.minecraft.commands.arguments.itemComponentPredicateParser$Context#createComponentTest,createPredicateTestnow takes in aDynamicinstead of aTagItemPredicateArgument$ComponentWrapper#decodenow takes in aDynamicinstead of aRegistryOps,Tagpair$PredicateWrapper#decodenow takes in aDynamicinstead of aRegistryOps,Tagpair
net.minecraft.coreBlockMathVANILLA_UV_TRANSFORM_LOCAL_TO_GLOBAL,VANILLA_UV_TRANSFORM_GLOBAL_TO_LOCALis now privategetUVLockTransform->getFaceTransformation
Direction#rotatenow takes in aMatrix4fcinstead of aMatrix4fRotationsis now a record
net.minecraft.data.loot.BlockLootSubProvider#createPetalDrops->createSegmentedBlockDropsnet.minecraft.networkFriendlyByteBufwriteLongArray,readLongArraynow have static delegates which take in theByteBufand*Fixed*versions for fixed size arrays
ProtocolInfo$Unbound->$Details,net.minecraft.network.protocol.SimpleUnboundProtocol,net.minecraft.network.protocol.UnboundProtocol; not one-to-one#bind->net.minecraft.network.protocol.SimpleUnboundProtocol#bind,UnboundProtocol#bind; not one-to-one
SkipPacketExceptionis now an interface instead of a subclass ofEncoderException
net.minecraft.network.chatComponentSerialization#flatCodec->flatRestrictedCodecLastSeenMessages$Updatenow takes in a byte representing the checksum valueLastSeenMessagesValidatorapplyOffsetnow returns nothing and can throw a$ValidationExceptionapplyUpdatenow returns the raw messages and can throw a$ValidationException
net.minecraft.network.codec.StreamCodec#compositenow has an overload for nine parametersnet.minecraft.network.protocol.ProtocolInfoBuildernow takes in a third generic representing how to modify the provided codec.addPacketnow has an overload that takes in aCodecModifierbuild->buildUnbound, not one-to-oneprotocol,serverboundProtocol,clientboundProtocolnow returns aSimpleUnboundProtocol
net.minecraft.network.protocol.ConfigurationProtocolsnow containSimpleUnboundProtocolconstantsnet.minecraft.network.protocol.gameClientboundContainerSetContentPacketis now a recordClientboundMoveEntityPacket#getyRot,getxRot->getYRot,getXRotClientboundPlayerChatPacketnow takes in a global index for the chat messageClientboundLevelChunkPacketdata#getHeightmapsnow returns aMap<Heightmap.Types, long[]>ClientboundUpdateAdvancementsPacketnow takes in a boolean representing whether to show the adavncements as a toastGameProtocolsconstants are now eitherSimpleUnboundProtocols orUnboundProtocolsServerboundContainerClickPacketis now a recordServerboundMovePlayerPacket$Pos,$PosRotnow has an overload that takes in aVec3for the positionServerboundSetStructureBlockPacketnow takes in an additional boolean representing whether the structure should be generated in strict mode
net.minecraft.network.protocol.handshake.HandshakeProtocols#SERVERBOUND_TEMPLATEis now aSimpleUnboundProtocolnet.minecraft.network.protocol.login.LoginProtocols#SERVERBOUND_TEMPLATEconstants are nowSimpleUnboundProtocolsnet.minecraft.network.protocol.status.StatusProtocols#SERVERBOUND_TEMPLATEconstants are nowSimpleUnboundProtocolsnet.minecraft.server.PlayerAdvancements#flushDirtynow takes in a boolean that represents whether the advancements show display as a toastnet.minecraft.server.bossevents.CustomBossEventsave->pack, not one-to-oneloadnow takes in the id and the packed variant to unpack
net.minecraft.server.levelDistanceManagerhasPlayersNearbynow returns aTriStateforEachBlockTickingChunks->forEachEntityTickingChunk, not one-to-one
ServerEntitynow takes in a consumer for broadcasting a packet to all players but those in the ignore listServerLevelgetForcedChunks->getForceLoadedChunksisPositionTickingWithEntitiesLoadedis now publicisNaturalSpawningAllowed->canSpawnEntitiesInChunk,BlockPosvariant is removed
ServerPlayergetRespawnPosition,getRespawnAngle,getRespawnDimension,isRespawnForced->getRespawnConfig, not one-to-onesetRespawnPositionnow takes in a$RespawnConfiginstead of the individual respawn informationloadAndSpawnParentVehicle,loadAndSpawnEnderpearlsnow takes in aCompoundTagwithout the optional wrapping\
net.minecraft.server.network.ServerGamePacketListenerImplnow implementsGameProtocols$Contextnet.minecraft.sounds.SoundEventshave the following sounds nowHolderwrapped:ITEM_BREAKSHIELD_BLOCK,SHIELD_BREAK,WOLF_ARMOR_BREAK
net.minecraft.utilBrightnessFULL_BRIGHTis now finalpacknow has a static overload that takes in the block and sky light.
ExtraCodecs#MATRIX4fnow is aCodec<Matrix4fc>Util#makeEnumMapreturns theMapsuperinstance rather than the specificEnumMap
net.minecraft.util.parsing.packrat.commands.TagParseRulenow takes in a generic for the tag type- The construct is now public, taking in a
DynamicOps
- The construct is now public, taking in a
net.minecraft.util.profilingActiveProfilernow takes in aBooleanSupplierinstead of a booleanContinuousProfilernow takes in aBooleanSupplierinstead of a boolean
net.minecraft.util.worldupdate.WorldUpgradernow takes in the currentWorldDatanet.minecraft.worldBossEvent$BossBarColor,$BossBarOverlaynow implementsStringRepresentableContainernow implementsIterable<ItemStack>
net.minecraft.world.effectMobEffectgetBlendDurationTicks->getBlendInDurationTicks,getBlendOutDurationTicks,getBlendOutAdvanceTicks; not one-to-onesetBlendDurationnow has an overload that takes in three integers to set the blend in, blend out, and blend out advance ticks
MobEffectInstance#tick->tickServer,tickClient; not one-to-one
net.minecraft.world.entityEntitycancelLerp->InterpolationHandler#cancellerpTo->moveOrInterpolateTolerpTargetX,lerpTargetY,lerpTargetZ,lerpTargetXRot,lerpTargetYRot->getInterpolationonAboveBubbleCol->onAboveBubbleColumnnow takes in aBlockPosfor the bubble column particles spawn location- Logic delegates to the protected static
handleOnAboveBubbleColumn
- Logic delegates to the protected static
isControlledByOrIsLocalPlayer->isLocalInstanceAuthoritative, now finalisControlledByLocalInstance->isLocalClientAuthoritative, now protectedisControlledByClient->isClientAuthoritativefallDistance,causeFallDamageis now a doubleabsMoveto->absSnapToabsRotateTo->asbSnapRotationTomoveTo->snapTosendBubbleColumnParticlesis now static, taking in theLevelonInsideBubbleColumnlogic delegates to the protected statichandleOnInsideBubbleColumn
EntityTypePOTION->SPLASH_POTION,LINGERING_POTION, not one-to-one$EntityFactory#createcan now return a null instance
ExperienceOrb#value->DATA_VALUEItemBasedSteeringno longer takes in the accessor for having a saddleLivingEntitylastHurtByPlayerTime->lastHurtByPlayerMemoryTimelerpSteps,lerpX,lerpY,lerpZ,lerpYRot,lerpXRot->interpolation, not one-to-oneisAffectedByFluidsis now publicremoveEffectNoUpdateis now finaltickHeadTurnnow returns nothingcanDisableShield->canDisableBlocking, now set via theWEAPONdata componentcalculateFallDamagenow takes in a double instead of a float
MobhandDropChances,armorDropChances,bodyArmorDropChance->dropChances, not one-to-onegetEquipmentDropChance->getDropChances, not one-to-one
net.minecraft.world.entity.ai.Brain#addActivityWithConditionsnow has an overload that takes in an integer indiciating the starting prioritynet.minecraft.world.entity.ai.behaviorLongJumpToRandomPos$PossibleJumpis now a recordVillagerGoalPackages#get*Packagenow takes in a holder-wrapped profession
net.minecraft.world.entity.ai.gossip.GossipContainer#store,update->clear,putAll,copy; not one-to-onenet.minecraft.world.entity.animalPigis now aVariantHolderSheep->.sheep.SheepWaterAnimal#handleAirSupplynow takes in aServerLevel
net.minecraft.world.entity.animal.axolotl.Axolotl#handleAirSupplynow takes in aServerLevelnet.minecraft.world.entity.monster.ZombieVillager#setGossipsnow takes in aGossipContainernet.minecraft.world.entity.monster.warden.WardenSpawnTrackernow has an overload which sets the initial parameters to zeronet.minecraft.world.entity.npcVillagernow takes in either a key or a holder of theVillagerTypesetGossipsnow takes in aGossipContainer
VillagerDatais now a recordset*->with*
VillagerProfessionnow takes in aComponentfor the nameVillagerTradesTRADESnow takes in a resource key as the key of the map- This is similar for all other type specific trades
$FailureItemListingis now private
net.minecraft.world.entity.player.PlayerstopFallFlying->LivingEntity#stopFallFlyingisSpectator,isCreativeno longer abstract in thePlayerclass
net.minecraft.world.entity.projectile.ThrownPotion->AbstractThrownPotion, implemented inThrownLingeringPotionandThrownSplashPotionnet.minecraft.world.entity.raid.Raid(int, ServerLevel, BlockPos)->Raid(BlockPos, Difficulty)tick,addWaveMobnow takes in theServerLevel
net.minecraft.world.entity.vehicleAbstractMinecart#setDisplayBlockState->setCustomDisplayBlockStateMinecartBehaviorcancelLerp->InterpolationHandler#cancellerpTargetX,lerpTargetY,lerpTargetZ,lerpTargetXRot,lerpTargetYRot->getInterpolation
MinecartTNT#primeFusenow takes in theDamageSourcecause
net.minecraft.world.inventoryAbstractContainerMenusetRemoteSlotNoCopy->setRemoteSlotUnsafe, not one-to-onesetRemoteCarriednow takes in aHashedStack
ClickTypenow takes in an id for its representationsContainerSynchronizer#sendInitialDatanow takes in a list of stacks rather than aNonNullList
net.minecraft.world.itemEitherHoldernow takes in anEitherinstance rather than just anOptionalholder andResourceKeyItemcanAttackBlock->canDestroyBlockhurtEnemyno longer returns anythingonCraftedByno longer takes in a separateLevelinstance, now relying on the one provided by thePlayer
ItemStackvalidateStrictis now publiconCraftedByno longer takes in a separateLevelinstance, now relying on the one provided by thePlayer
MapItemcreatenow takes in aServerLevelinstead of aLevellockMapis now private
ThrowablePotionItemis now abstract, containing two methods to create theAbstractThrownPotionentityWrittenBookItem#resolveBookComponents->WrittenBookContent#resolveForItem
net.minecraft.world.item.alchemy.PotionContentsnow implementsTooltipProviderforEachEffect,applyToLivingEntitynow takes in a float representing a scalar for the duration
net.minecraft.world.item.component.WrittenBookContentnow implementsTooltipProvidernet.minecraft.world.item.craftingSmithingRecipe#baseIngredientnow returns anIngredientSmithingTransformRecipenow takes in aTransmuteResultinstead of anItemStackand anIngredientfor the baseSmithingTrimRecipenow takes inIngredients instead ofOptionalwrapped entries along with aTrimPatternholderTransmuteRecipenow takes in aTransmuteResultinstead of anItemholder
net.minecraft.world.item.crafting.display.SlotDisplay$SmithingTrimDemoSlotDisplaynow takes in aTrimPatternholdernet.minecraft.world.item.enchantment.EnchantmentInstanceis now a recordnet.minecraft.world.levelBlockGetter#boxTraverseBlocks->forEachBlockIntersectedBetween, not one-to-oneCustomSpawner#tickno longer returns anythingGameRules$Typenow takes in a value classLevelonBlockStateChange->updatePOIOnBlockStateChangeisDay->isBrightOutsideisNight->isDarkOutsidesetMapData->net.minecraft.server.level.ServerLevel#setMapDatagetFreeMapId->net.minecraft.server.level.ServerLevel#getFreeMapId
LevelAccessor#blockUpdated->updateNeighborsAt
net.minecraft.world.level.biome.MobSpawnSettings$SpawnerDatais now a recordnet.minecraft.world.level.blockAttachedStemBlocknow extendsVegetationBlockAzaleaBlocknow extendsVegetationBlockBlock#fallOnnow takes a double for the fall damage instead of a floatBushBlocknow extendsVegetationBlockand implementsBonemealableBlockColoredFallingBlock#dustColoris now protectedCropBlocknow extendsVegetationBlockDeadBushBlock->DryVegetationBlockDoublePlantBlocknow extendsVegetationBlockFallingBlock#getDustColoris now abstractFlowerBedBlocknow extendsVegetationBlockFlowerBlocknow extendsVegetationBlockFungusBlocknow extendsVegetationBlockLeafLitterBlocknow extendsVegetationBlockLeavesBlockis now abstract, taking in the chance for a particle to spawn- Particles are spawned via
spawnFallingLeavesParticle
- Particles are spawned via
MangroveLeavesBlocknow extendsTintedParticleLeavesBlockMushroomBlocknow extendsVegetationBlockNetherSproutsBlocknow extendsVegetationBlockNetherWartBlocknow extendsVegetationBlockParticleLeavesBlock->LeafLitterBlockPinkPetalsBlock->FlowerBedBlockRootsBlocknow extendsVegetationBlockRotationnow has an index used for syncing across the networkSaplingBlocknow extendsVegetationBlockSeagrassBlocknow extendsVegetationBlockSeaPickleBlocknow extendsVegetationBlockStemBlocknow extendsVegetationBlockSweetBerryBushBlocknow extendsVegetationBlockTallGrassBlocknow extendsVegetationBlockTntBlock#primenow returns whether the primed tnt was spawned.WaterlilyBlocknow extendsVegetationBlock
net.minecraft.world.level.block.entityBlockEntityparseCustomNameSafenow takes in a nullableTaginstead of a stringgetPosFromTagnow takes in theChunkPos$ComponentHolder#COMPONENTS_CODECis now aMapCodec
BLockEntityType#createis no longer nullable
net.minecraft.world.level.block.entity.trialspawner.TrialSpawner#codecnow returns aMapCodecnet.minecraft.world.level.block.state.StateHoldergetNullableValueis now privatehasPropertyno longer contains a generic
net.minecraft.world.level.chunkChunkAccess#setBlockStatenow takes in the block flags instead of a boolean, and has an overload to update all setLevelChunk#replaceWithPacketDatanow takes in aMap<Heightmap$Types, long[]>instead of aCompoundTag
net.minecraft.world.level.chunk.storage.SerializableChunkData#getChunkTypeFromTag->getChunkStatusFromTag, not one-to-onenet.minecraft.world.level.gameevent.vibrations.VibrationSystem#DEFAULT_VIBRATION_FREQUENCY->NO_VIBRATION_FREQUENCYnet.minecraft.world.level.levelgen.feature.TreeFeature#isVineis now publicnet.minecraft.world.level.levelgen.structure.pools.aliasDirect->DirectPoolAliasRandom->RandomPoolAliasRandomGroup->RandomGroupPoolAlias
net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate$JigsawBlockInfonow takes in aResourceKeyto theStructureTemplatePoolinstead of a rawResourceLocationnet.minecraft.world.level.saveddata.maps.MapFrameis now a recordsave,load->CODEC, not one-to-one
net.minecraft.world.level.storage.loot.functions.SetWrittenBookPagesFunction#PAGE_CODEC->WrittenBookContent#PAGES_CODECnet.minecraft.world.scoresScore#write->CODEC, not one-to-oneScoreboardsavePlayerScores->packPlayerScores, not one-to-oneloadPlayerScores->loadPlayerScore, not one-to-one
Team$CollisionRule,$Visibilityare nowStringRepresentable
net.minecraft.world.phys.shapes.EntityCollisionContextnow takes in a boolean representing if it is used for placing a blocknet.minecraft.world.ticks.SavedTickloadTick,saveTick,save->codec, not one-to-oneloadTickList->filterTickListForChunk, not one-to-one
List of Removals
com.mojang.blaze3d.vertex.BufferUploadernet.minecraft.core.Rotations#getWrapped*net.minecraft.network.chat.ComponentSerialization#FLAT_CODECnet.minecraft.network.protocol.gameClientboundAddExperimentOrbPacketClientGamePacketListener#handleAddExperienceOrb
net.minecraft.resources.ResourceLocation$Serializernet.minecraft.server.network.ServerGamePacketListenerImpl#addPendingMessagenet.minecraft.worldBossEvent$BossBarColor#byName,$BossBarOverlay#byNameClearable#tryClear
net.minecraft.world.effect.MobEffectInstance#save,loadnet.minecraft.world.entityEntityisInBubbleColumnisInWaterRainOrBubble,isInWaterOrBubblenewDoubleList,newFloatListrecordMovementThroughBlocks
EntityEvent#ATTACK_BLOCKED,SHIELD_DISABLEDItemBasedSteeringaddAdditionalSaveData,readAdditionalSaveDatasetSaddle,hasSadddle
LivingEntitytimeOffs,rotOffsrotAoRun,runanimStep,animStep0appliedScalecanBeNameTagged
MobDEFAULT_EQUIPMENT_DROP_CHANCEPRESERVE_ITEM_DROP_CHANCE_THRESHOLD,PRESERVE_ITEM_DROP_CHANCE
NeutralMob#setLastHurtByPlayerPositionMoveRotation#ofEntityUsingLerpTarget
net.minecraft.world.entity.ai.attributes.AttributeModifier#save,loadnet.minecraft.world.entity.animalDolphin#setTreasurePos,getTreasurePosFox$Variant#byNameMushroomCow$Variant#byNamePanda$Gene#byNameSalmon$Variant#byNameTurtlegetHomePossetTravelPos,getTravelPosisGoingHome,setGoingHomeisTravelling,setTravelling
net.minecraft.world.entity.animal.armadillo.Armadillo$ArmadilloState#fromNamenet.minecraft.world.entity.npc.VillagerTrades#EXPERIMENTAL_WANDERING_TRADER_TRADESnet.minecraft.world.entity.projectile.AbstractArrow#getBaseDamagenet.minecraft.world.entity.raid.RaidgetLevel,getIdsave
net.minecraft.world.entity.vehicle.AbstractMinecart#hasCustomDisplay,setCustomDisplaynet.minecraft.world.item.ItemStack#parseOptional,saveOptionalnet.minecraft.world.item.equipment.trim.TrimPattern#templateItemnet.minecraft.world.level.Level#updateNeighborsAt(BlockPos, Block)net.minecraft.world.level.block.entityCampfireBlockEntity#dowsePotDecorations#save,load
net.minecraft.world.level.levelgen.BelowZeroRetrogen#readnet.minecraft.world.level.levelgen.structure.structures.RuinedPortalPiece$VerticalPlacement#byNamenet.minecraft.world.level.saveddata.maps.MapBanner#LIST_CODECnet.minecraft.world.scores.Team$CollisionRule#byName$Visibility#getAllNames,byName
net.minecraft.world.ticks.LevelChunkTicks#save,load