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.appendStackstoo.- 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
FabricBuiltinRegistriesProvideris 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
blockfolder (or any subfolder) - All textures in the
itemfolder (or any subfolder) - All textures in the
entity/conduitfolder (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);
});UnbakedModels 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:
SignedMessagecontinues to exist, and holds the newly addedMessageLinkinstead of the now-removedMessageHeader.MessageLinkcontains 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.ProfilelessChatMessageS2CPacketis now used to send profileless chat messages (i.e. command-sent message invoked from/executeor 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.
LastSeenMessageListserialization 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
sendChatMessageandsendCommandmethods have been moved fromClientPlayerEntitytoClientPlayNetworkHandler. ChatLogis no longer an interface and is instead an implementation class. There's alsoMessageSignatureStorage, aChatLog-like class but available everywhere.DecoratableArgumentListis renamedSignedArgumentList.DecoratableArgumentTypeinterface 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:
PacketByteBufcan now serializeBitSetwith 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). PlayerListS2CPacketis 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,REMOTEfor 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:
ResourceFinderis added. This, when given a resource manager, returns the map of IDs toResources. 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. ResourceMetadataMapis added, which acts as a map of all resource metadatas of a resource pack profile.DataConfigurationis a new class that holdsDataPackSettingsand enabledFeatureSet.FileNameUtilreceived 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 likeRegistryPredicateArgumentTypebut 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.
Identifierconstructor 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).Identifieralso got several methods for manipulating the path.AbstractButtonBlock,DoorBlock,PressurePlateBlock, andWeightedPressurePlateBlockconstructors now take the sounds it makes. Wooden/stone button subclasses are removed because it is obsoleted.createAndScheduleBlockTickandcreateAndScheduleFluidTickmethods are renamed toscheduleBlockTickandscheduleFluidTickrespectively.
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.TrackedDataHandlerRegistrynow contains the handlerLONG.AbstractHorseEntityreceived new methods:jump,shouldAmbientStand,getHorsebackMovementSpeed,ignoresMovementInput,equipHorseArmor,getAmbientStandSound, andgetMinAmbientStandDelay.AbstractBlock.Settings#noBlockBreakParticlesandAbstractBlock.AbstractBlockState#hasBlockBreakParticlesfor blocks that don't emit breaking particles like barriers.AbstractBlock.AbstractBlockState#isReplaceablewhich returns whether the block material is replaceable.Properties#LAST_INTERACTION_BOOK_SLOTandProperties#BOOKS_STORED, probably not useful for modders.RotationPropertyHelper, which performs conversions between rotation degrees and rotation properties.Entity#requestTeleportOffsetwhich works likerequestTeleportbut with an offset instead of absolute position.ItemStack#isItemEnabledthat returns whether the feature toggle for the item is enabled.World#playSoundoverload that takesBlockPos.World#playSoundAtBlockCenterthat plays the sound at the center of the given position (adding0.5), which should be used for blocks playing sounds.AbstractCookingRecipe#getCategoryandCraftingRecipe#getCategory, which return the category of the recipes.LivingEntity#getAttributeValueandLivingEntity#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
TextReorderingProcessoris repackaged fromclient.resource.languagetotextbecause it is not client exclusive.DynamicSerializableUuidis repackaged fromutil.dynamictoutiland is renamed toUuids.OreBlockis renamed toExperienceDroppingBlockbecause 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.
SetGoatHornSoundLootFunctionis renamed toSetInstrumentLootFunction.WallStandingBlockItemis renamed toVerticallyAttachableBlockItembecause it can now be used for hanging blocks as well.TickPriorityis repackaged fromworldtoworld.tick.ColorResolveris repackaged fromworld.leveltoworld.biome.AbstractButtonBlockis renamed toButtonBlock.CommandBlockItemis renamed toOperatorOnlyBlockItem.