Skip to content

Instantly share code, notes, and snippets.

@apple502j
Last active January 2, 2023 08:17
Show Gist options
  • Save apple502j/a498c84f089ffce2b563bfe684ac24d7 to your computer and use it in GitHub Desktop.
Save apple502j/a498c84f089ffce2b563bfe684ac24d7 to your computer and use it in GitHub Desktop.
22w42a docs

22w42a: The Catastrophe Update

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.

Read/watch this first!

They provide the basic info of this snapshot.

Toolchain

Version schema

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+ required

Loader 0.14.10+ is required for 22w42a.

Fabric API

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, replaces fabric-item-groups-v0)
  • fabric-textures-v0 (2.0.0)

Changes

Feature flags

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.

Item group changes, affecting almost all content mods

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.

Dynamic registry loading changes (modder-facing)

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.

Texture API and Sprite changes

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);
});

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.

Data generator changes

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);
    }
}

Chat/networking changes

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 added MessageLink instead of the now-removed MessageHeader.
  • 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 used ChatMessageS2CPacket.
  • Two "session" classes are added: ClientPlayerSession (client-side class) and PublicPlayerSession (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 and sendCommand methods have been moved from ClientPlayerEntity to ClientPlayNetworkHandler.
  • ChatLog is no longer an interface and is instead an implementation class. There's also MessageSignatureStorage, a ChatLog-like class but available everywhere.
  • DecoratableArgumentList is renamed SignedArgumentList. 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 serialize BitSet with predefined size, authlib PropertyMap, and EnumSet.
  • There are 3 new S2C packets: ProfilelessChatMessage, PlayerRemove (sent when a player is disconnected), and Features (sends the feature set enabled by the server).
  • PlayerListS2CPacket is refactored. Its action now includes INITIALIZE_CHAT (sending public player session after login) and UPDATE_LISTED (allows hiding players from player list).

Registry changes (the boring part)

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 and STATIC, 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).

Resource loading changes

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 to Resources. 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 just Supplier<T> that can throw IOException.
  • ResourceMetadataMap is added, which acts as a map of all resource metadatas of a resource pack profile.
  • DataConfiguration is a new class that holds DataPackSettings and enabled FeatureSet.
  • FileNameUtil received several Path-related utilities, mostly for validating path. This class is now renamed to PathUtil.

Command changes

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 of RegistryEntry<T>
  • RegistryEntryPredicateArgumentType, which works like RegistryPredicateArgumentType but the entry is either named RegistryEntryList (tags) or RegistryEntry (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.

Other changes

  • Identifier constructor no longer allocates an array, potentially improving performance. There is a new constructor that takes ExtraData (an unused interface presumably intended to be used by mods). Identifier also got several methods for manipulating the path.
  • AbstractButtonBlock, DoorBlock, PressurePlateBlock, and WeightedPressurePlateBlock constructors now take the sounds it makes. Wooden/stone button subclasses are removed because it is obsoleted.
  • createAndScheduleBlockTick and createAndScheduleFluidTick methods are renamed to scheduleBlockTick and scheduleFluidTick respectively.

Additions

  • ItemStackSet, a hash set of item stacks that use ItemStack#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 handler LONG.
  • AbstractHorseEntity received new methods: jump, shouldAmbientStand, getHorsebackMovementSpeed, ignoresMovementInput, equipHorseArmor, getAmbientStandSound, and getMinAmbientStandDelay.
  • AbstractBlock.Settings#noBlockBreakParticles and AbstractBlock.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 and Properties#BOOKS_STORED, probably not useful for modders.
  • RotationPropertyHelper, which performs conversions between rotation degrees and rotation properties.
  • Entity#requestTeleportOffset which works like requestTeleport 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 takes BlockPos.
  • World#playSoundAtBlockCenter that plays the sound at the center of the given position (adding 0.5), which should be used for blocks playing sounds.
  • AbstractCookingRecipe#getCategory and CraftingRecipe#getCategory, which return the category of the recipes.
  • LivingEntity#getAttributeValue and LivingEntity#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

Renames and repackages not covered elsewhere

  • TextReorderingProcessor is repackaged from client.resource.language to text because it is not client exclusive.
  • DynamicSerializableUuid is repackaged from util.dynamic to util and is renamed to Uuids.
  • OreBlock is renamed to ExperienceDroppingBlock 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 to SetInstrumentLootFunction.
  • WallStandingBlockItem is renamed to VerticallyAttachableBlockItem because it can now be used for hanging blocks as well.
  • TickPriority is repackaged from world to world.tick.
  • ColorResolver is repackaged from world.level to world.biome.
  • AbstractButtonBlock is renamed to ButtonBlock.
  • CommandBlockItem is renamed to OperatorOnlyBlockItem.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment