22w42a, the first and hopefully only snapshot for 1.19.3: The Catastrophe Update is here! I'm not joking. Remember the 22w06a update that refactored registries and tags completely? The same thing happened - although this time, in all places.
They provide the basic info of this snapshot.
Mojang now uses the "Bedrock versioning", where a dot update is used to bring future updates ahead of time. Expect all future dot releases to be as big as major updates (think of it like 1.16.2 or 1.18.2 every few months). If you have a mod, we encourage you to set it as "depends on MC <=1.19.2
".
Loader 0.14.10+ is required for 22w42a.
Fabric API version 0.65.0 can be used. Note that several modules received breaking changes, see below for more info:
fabric-biome-api-v1
(10.0.0)fabric-data-generation-api-v1
(6.0.0)fabric-item-api-v1
(2.0.0)fabric-item-group-api-v1
(New API, replacesfabric-item-groups-v0
)fabric-textures-v0
(2.0.0)
This is actually straightforward. Feature flags were added, for descriptions on what they are please check the slicedlime video.
Feature flags are predefined flags that a data pack can enable during the world creation. Currently, blocks, items, and entity types can be hidden behind the flag. If the flag is not enabled, the blocks etc still exist in the registry; however, the vanilla code prevents interactions with said blocks or items and does not allow spawning said entities. They implement ToggleableFeature
, and canUse
method can be used to see if the feature can be used. (ItemStack
also has isItemEnabled
method.)
The enabled feature flags can be obtained from the server via MinecraftServer#getEnabledFeatures
and on the client via ClientPlayNetworkHandler#getEnabledFeatures
. The enabled features are synced with a new packet.
TL;DR:
Item.Setting#group()
is gone.appendStacks
too.- Fabric Item Group API is now version 1 with completely new API. No compatibility layer provided.
Mojang refactored item group system. Item group contents are no longer registered using item settings or item classes; they are instead defined inside ItemGroup
. This complicates adding your items to the group a bit, therefore a new Fabric API is module created.
// 1.19.2
Item MY_ITEM = new Item(new Item.Settings().group(ItemGroup.MISC));
// 22w42a
ItemGroupEvents.modifyEntriesEvent(ItemGroups.CRAFTING).register(entries -> entries.add(MY_ITEM));
// You can now also control the order or visibility
ItemGroupEvents.modifyEntriesEvent(ItemGroups.CRAFTING).register(
entries -> entries.add(UNSEARCHABLE_ITEM, ItemGroup.StackVisibility.PARENT_TAB_ONLY)
));
ItemGroupEvents.modifyEntriesEvent(ItemGroups.REDSTONE).register(
entries -> entries.addAfter(Items.REDSTONE, BLUESTONE, BLUESTONE_TORCH) // can supply multiple arguments
));
// To add items to your own item groups, do it in the item group (see below)
// Adding to item groups from other mods using IDs
ItemGroupEvents.modifyEntriesEvent(new Identifier("other_mod", "magic")).register(entries -> entries.add(MAGIC_GEM));
// You can also use MODIFY_ENTRIES_ALL if you want to add your item to every item group (but please don't.)
You now extend a class to create your own item group, instead of using a builder:
// 1.19.2
ItemGroup MY_GROUP = FabricItemGroupBuilder.build(
new Identifier("my_mod", "example_group"),
() -> new ItemStack(MY_ITEM);
);
// 22w42a
// The identifier is used by other mods to identify the item group.
ItemGroup MY_GROUP = new FabricItemGroup(new Identifier("my_mod", "magic")) {
@Override
public ItemStack createIcon() {
return new ItemStack(Items.DIAMOND);
}
@Override
protected void addItems(FeatureSet enabledFeatures, Entries entries) {
entries.add(MAGIC_GEM);
}
};
Item API's sole breaking change is the removal of FabricItemSettings#group
.
TL;DR:
- If you are registering biomes etc. to
BuiltinRegistries
, you need to switch to JSON. - Datagen API
FabricBuiltinRegistriesProvider
is added to allow easy transition. - See below for internal changes and boring news on dynamic registry.
Mojang now includes the worldgen JSON file in the game jar and uses it for loading. This also meant that BuiltinRegistries
is no longer the source of vanilla (or modded) contents. In fact, that class is now only used during data generation. If your biome mod, structure mod, 1.19 message type mod etc. registers stuff into BuiltinRegistries
, you now need to generate its JSON and include it in the mod as a data pack.
To include a data pack, create data
folder in the resources
folder and put the contents there. For example, a modded biome would go to data/modid/worldgen/biome/biome_id.json
. You can also use FabricBuiltinRegistriesProvider
in the Data Generation API to generate JSON automatically from BuiltinRegistries
:
public class DataGeneratorEntrypoint implements net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint {
@Override
public void onInitializeDataGenerator(FabricDataGenerator dataGenerator) {
dataGenerator.addProvider(FabricBuiltinRegistriesProvider.forCurrentMod());
}
}
Biome modification API continues to work as before, and it will now provide a detailed error message when the objects couldn't be found in the registry.
The sprites that should be baked into texture atlases are no longer discovered by querying all UnbakedModel
during the model baking process. Instead, the SpriteAtlasManager
will independently search for textures using patterns in all available resource packs and bake them into specific texture atlases.
For example, BakedModelManager
defines the block atlas as:
- All textures in the
block
folder (or any subfolder) - All textures in the
item
folder (or any subfolder) - All textures in the
entity/conduit
folder (or any subfolder) - The texture at
BellBlockEntityRenderer.BELL_BODY_TEXTURE
- The texture at
EnchantingTableBlockEntityRenderer.BOOK_TEXTURE
Textures outside such directories cannot be referenced by default (e.g. textures/custom/
), which can break old resource packs. This is done to improve performance. To use such custom textures, use Fabric API's ClientSpriteRegistryCallback
event, which has been modified to allow new rules to be appended for any texture atlas.
For example, the following would add all textures from the subfolder part (recursively) to the atlas (from any resource pack/namespace), and also the texture called "ae2:models/skyblockchest" specifically.
ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE).register((resourceManager, sprites) -> {
// to be named SpriteLoader#addResource
class_7766.method_45834(resourceManager, "part", sprites::put);
class_7766.method_45830(resourceManager, new Identifier("ae2:models/skyblockchest"), sprites::put);
});
UnbakedModel
s no longer have texture dependencies (see Texture API), so the corresponding method was removed without a replacement. Other deprecated APIs of the Texture API are also dropped.
In addition, vanilla changed how parent models are loaded by JSON models. It introduced method_45785
(to be named setParents
) to allow a model to load its parent models. This method is only called for models that are initially added to the model load list. If your mod subclasses UnbakedModel
and uses nested JSON models, it should always call method_45785
on its own model dependencies. The used JSON models would not be able to load their parents otherwise.
DataGenerator
now takes DataOutput
as the argument instance of DataGenerator
; however, Fabric API data providers still take FabricDataGenerator
. (A new implementation class, FabricDataOutput
, allows data generator access.) DataGenerator#createPathResolver
is replaced with DataOutput#getResolver
.
There is one breaking change: generateStuff
methods (e.g. generateBlockLootTables
) are now provided from vanilla game and renamed to generate
. It is also now public
, not protected
.
public class TestBlockLootTableProvider extends FabricBlockLootTableProvider {
public TestBlockLootTableProvider(FabricDataGenerator dataGenerator) {
super(dataGenerator);
}
@Override
// Renamed from generateBlockLootTables and now public
public void generate() {
addDrop(SIMPLE_BLOCK);
}
}
Yep. Mojang changed chat again.
They removed chat preview (perhaps to close otherwise unsolveable exploits), reworked how messages are chained, refactored class relationship, etc.
The new class relations are as follows:
SignedMessage
continues to exist, and holds the newly addedMessageLink
instead of the now-removedMessageHeader
.MessageLink
contains the "session ID" (per-profile UUID randomly generated at every login), profile UUID, and the "index". The index is an integer indicating the index of the messages the sender signed. A message chain is considered valid if the newer message has a bigger index and the session ID and the profile ID are the same.ProfilelessChatMessageS2CPacket
is now used to send profileless chat messages (i.e. command-sent message invoked from/execute
or command block). Previously this usedChatMessageS2CPacket
.- Two "session" classes are added:
ClientPlayerSession
(client-side class) andPublicPlayerSession
(sent to all players).
Changes to the chat protocol:
- The switch to index-based chain (from signature chain) allows messages to be blocked server-side (for censoring, private message, etc) without sending the message header to everyone. Chain verification only checks that the index increased and does not check if it is sequencial. This fixes exploits with private message sender/recipient information being leaked.
LastSeenMessageList
serialization also became significantly smaller due to use of integer index.- Chat preview is removed, presumably due to (unproven) concerns on abuse. This also removed the now-unnecessary message decorator caching layer. Chat suggestion packet still exists, but is useless since the server cannot use it as "autocomplete" anymore.
- Messages no longer receive the indicator for style-only changes (changes that don't affect text or used fonts). Modified and unsigned messages' indicators are now grey, instead of orange or red.
- Message removal (previously called "hiding" in Yarn, but is renamed because practically it cannot be re-displayed) packet handling has changed. slicedlime video covers the details. In short: a message cannot be removed within the first 60 ticks of reception (it is instead queued for removal). Removed messages will then show that it was removed, instead of disappearing completely.
Other chat-related changes:
- The client-side
sendChatMessage
andsendCommand
methods have been moved fromClientPlayerEntity
toClientPlayNetworkHandler
. ChatLog
is no longer an interface and is instead an implementation class. There's alsoMessageSignatureStorage
, aChatLog
-like class but available everywhere.DecoratableArgumentList
is renamedSignedArgumentList
.DecoratableArgumentType
interface is removed.
// Old code
client.player.sendCommand("give @s minecraft:diamond");
// New code
client.player.networkHandler.sendCommand("give @s minecraft:diamond");
Other non-chat networking changes:
PacketByteBuf
can now serializeBitSet
with predefined size, authlibPropertyMap
, andEnumSet
.- There are 3 new S2C packets:
ProfilelessChatMessage
,PlayerRemove
(sent when a player is disconnected), andFeatures
(sends the feature set enabled by the server). PlayerListS2CPacket
is refactored. Its action now includesINITIALIZE_CHAT
(sending public player session after login) andUPDATE_LISTED
(allows hiding players from player list).
TL;DR:
- Mutable DRM is gone.
- Registry loading method has changed.
- There are now multiple instances of dynamic registry managers ("layered DRM"). The registries are now held in
CombinedDynamicRegistries
. - There is still one registry manager that combines all the layers, available via
World#getRegistryManager
. - Layers are
STATIC
,WORLDGEN
,DIMENSIONS
,RELOADABLE
(in the order of the layer) for the server-side andSTATIC
,REMOTE
for the client-side.
Along with the modder-facing changes (see above), there are also major reworks on DRM structure.
Previously there was one DynamicRegistryManager
created early during world loading phase and mutated when the data packs are loaded. Now, there are multiple of them. DRMs are now layered and each layer has its own DRM instance. For example, DIMENSIONS
layer only holds DimensionOptions
registry and is created very early in the loading process. WORLDGEN
contains all other world-gen related registries. The layering also meant that there is now no need to mutate an existing DRM instance, therefore DynamicRegistryManager.Mutable
is removed.
Those layered DRMs are all stored in CombinedDynamicRegistries
instance (obtained using getCombinedDynamicRegistries
method). Of course, modders don't usually want to deal with this low-level API; World#getRegistryManager
still returns DynamicRegistryManager
that has registries from all layers combined. (The same can be obtained from CombinedDynamicRegistries#getCombinedRegistryManager
.)
If you somehow need to load a registry manually, use RegistryLoader#load
instead of RegistryOps#ofLoaded
. DynamicRegistryManager#of
can be used to turn Registry.REGISTRIES
into a DRM. getOptional
and get
in DynamicRegistryManager
no longer fall back to Registry.REGISTRIES
(like the previous Managed
-suffixed methods, which have been removed).
Minecraft now uses custom filesystem to load resources. This shouldn't affect most users.
Default resource packs are now provided from VanillaResourcePackProvider
like VanillaDataPackProvider
. ClientBuiltinResourcePackProvider
's default pack loading is split into DefaultClientResourcePackProvider
; the class now only handles HTTP-based resource pack and is renamed to ServerResourcePackProvider
.
Other changes related to resources:
ResourceFinder
is added. This, when given a resource manager, returns the map of IDs toResource
s. This is now the preferred way of finding resources that are loaded. For example:
public static final ResourceFinder JSON_FINDER = ResourceFinder.json("tiny_potatoes");
public static final ResourceFinder PNG_FINDER = new ResourceFinder("tiny_potatoes", ".png");
// to use:
JSON_FINDER.findResources(resourceManager).forEach((id, resource) -> {});
- Some methods now return
InputSupplier<T>
, which is justSupplier<T>
that can throwIOException
. ResourceMetadataMap
is added, which acts as a map of all resource metadatas of a resource pack profile.DataConfiguration
is a new class that holdsDataPackSettings
and enabledFeatureSet
.FileNameUtil
received severalPath
-related utilities, mostly for validating path. This class is now renamed toPathUtil
.
Several command argument types are removed and consolidated. They include: EnchantmentArgumentType
, EnchantmentArgumentType
, and EntitySummonArgumentType
. There are 2 new argument types that replace those.
RegistryEntryArgumentType
, which is an argument type ofRegistryEntry<T>
RegistryEntryPredicateArgumentType
, which works likeRegistryPredicateArgumentType
but the entry is either namedRegistryEntryList
(tags) orRegistryEntry
(one entry)
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(
literal("custom_summon").then(
argument("entity", RegistryEntryArgumentType.registryEntry(registryAccess, Registry.ENTITY_TYPE_KEY))
.executes(MyCommand::execute)));
dispatcher.register(
literal("find").then(
argument("entity", RegistryEntryPredicateArgumentType.registryEntryPredicate(registryAccess, Registry.ENTITY_TYPE_KEY))
.executes(AnotherCommand::execute)));
});
// get the argument
Entity entity = getRegistryEntry(context, "entity", Registry.ENTITY_TYPE_KEY).value();
// or, just use getSummonableEntityType, which also filters unsummonable entities
// using RegistryEntryPredicateArgumentType
RegistryEntryPredicateArgumentType.EntryPredicate predicate = getRegistryEntryPredicate(context, "entity", Registry.ENTITY_TYPE_KEY);
List<Entity> entities = world.getOtherEntities(source.getPlayer(), box, predicate);
They use CommandRegistryAccess
to access the registry. CommandRegistryAccess
now also stores the enabled feature flags. CommandSource#getEnabledFeatures
can also be used to get the flags.
Identifier
constructor no longer allocates an array, potentially improving performance. There is a new constructor that takesExtraData
(an unused interface presumably intended to be used by mods).Identifier
also got several methods for manipulating the path.AbstractButtonBlock
,DoorBlock
,PressurePlateBlock
, andWeightedPressurePlateBlock
constructors now take the sounds it makes. Wooden/stone button subclasses are removed because it is obsoleted.createAndScheduleBlockTick
andcreateAndScheduleFluidTick
methods are renamed toscheduleBlockTick
andscheduleFluidTick
respectively.
ItemStackSet
, a hash set of item stacks that useItemStack#areEqual
(compares item, item count, and NBT).JumpingMount#getDashCooldown
, which returns the dash cooldown of a jumping mount (horses and camels).Saddleable#getSaddleSound
, which returns the sound event for saddling a rideable entity.ClientPlayerEntity#getJumpingMount
, which returns the jumping mount the player is riding.TrackedDataHandlerRegistry
now contains the handlerLONG
.AbstractHorseEntity
received new methods:jump
,shouldAmbientStand
,getHorsebackMovementSpeed
,ignoresMovementInput
,equipHorseArmor
,getAmbientStandSound
, andgetMinAmbientStandDelay
.AbstractBlock.Settings#noBlockBreakParticles
andAbstractBlock.AbstractBlockState#hasBlockBreakParticles
for blocks that don't emit breaking particles like barriers.AbstractBlock.AbstractBlockState#isReplaceable
which returns whether the block material is replaceable.Properties#LAST_INTERACTION_BOOK_SLOT
andProperties#BOOKS_STORED
, probably not useful for modders.RotationPropertyHelper
, which performs conversions between rotation degrees and rotation properties.Entity#requestTeleportOffset
which works likerequestTeleport
but with an offset instead of absolute position.ItemStack#isItemEnabled
that returns whether the feature toggle for the item is enabled.World#playSound
overload that takesBlockPos
.World#playSoundAtBlockCenter
that plays the sound at the center of the given position (adding0.5
), which should be used for blocks playing sounds.AbstractCookingRecipe#getCategory
andCraftingRecipe#getCategory
, which return the category of the recipes.LivingEntity#getAttributeValue
andLivingEntity#getAttributeBaseValue
, which return the attribute value and base attribute value of an entity respectively.BlockPredicate#noFluid
, which is a block predicate to disallow replacing fluids
TextReorderingProcessor
is repackaged fromclient.resource.language
totext
because it is not client exclusive.DynamicSerializableUuid
is repackaged fromutil.dynamic
toutil
and is renamed toUuids
.OreBlock
is renamed toExperienceDroppingBlock
because sculk is not an ore.- Data generator classes are repackaged by the provider's type (such as loot table or recipe) due to increase in size with the addition of experimental feature providers.
SetGoatHornSoundLootFunction
is renamed toSetInstrumentLootFunction
.WallStandingBlockItem
is renamed toVerticallyAttachableBlockItem
because it can now be used for hanging blocks as well.TickPriority
is repackaged fromworld
toworld.tick
.ColorResolver
is repackaged fromworld.level
toworld.biome
.AbstractButtonBlock
is renamed toButtonBlock
.CommandBlockItem
is renamed toOperatorOnlyBlockItem
.