This post is a guide for Tinkers’ Construct addon authors to update to the latest API in 1.20. As the version stabilizes, this page will get updated with any new API changes or notable deprecations. See #5281 for likely upcoming breaking changes.

Update Summary

As new alphas are released, we plan to update this primer to ensure all information is in one place. On the chance you updated your addon to an earlier addon, you may find the following useful to link to you just what changed in later alphas.

Forge

This only covers information specific to Tinkers’ Construct; for general information see the following mod migration primers from ChampionAsh5357:

3.9.1

Data packs

Java

Mantle

Data Packs

Modifier Serializer Removal

Modifier serializers have now been fully removed in favor of modifier modules. The modifier JSON syntax now requires the type to be “composable”, meaning it gets the full module loader. All functionality that was previously in a modifier serializer exists in a modifier module.

If you are a modder who previously wrote a modifier serializer, it is very simple to migrate to a module; you basically implement the same interfaces plus ModifierModule, using any object (including a record) as the base class. If you were relying on a specific class with a DynamicModifier with a type filter, that is no longer possible; instead make use of a custom ModuleHook implemented by a custom module for the required behavior.

Damage Predicates

Damage predicates got significantly reworked due to Mojang migrating most fields to tags. As a result, many simple damage predicates have been moved to tag predicates. See the relevant doc for available predicates.

Damage Fluid Effect

Damage fluid effects now contain an object damage_type containing fields melee and ranged to apply behavior to the damage dealt by the fluid. The fields refer to the IDs of two damage types used for melee and ranged fluid attacks respectively. Behaviors that were previously added in this JSON are now added via damage type tags.

This change is made as the recent changes to damage sources means damage type tags are the only way to apply these behaviors. They also provide much greater flexibility.

Removed explosion knockback armor stat

The armor stat tconstruct:explosion_knockback was removed (usable notably in module types tconstruct:armor_stat and tconstruct:max_armor_stat) in favor of the vanila enchantment which was recently fixed. The handler was a pretty large hack so its more efficient to remove it (plus Mojang will add an attribute with the same behavior come 1.21).

This armor stat was added late in 1.19.2 so this change is unlikely to affect many mods.

Part Chest Items

The part chest no longer holds all items that extend IMaterialItem. Instead, you must add items to the item tag tconstruct:chest_parts. All items under tconstruct:parts are automatically added to this tag (which you should be tagging your tool parts as anyways).

Side Inventory Whitelist

Since 3.9.1
  • The Crafting Station, Part Builder, and Modifier Worktable now use a whitelist for side inventories instead of a blacklist.
  • Whitelist can be found at the block entity tag tconstruct:side_inventories.
  • Relevant vanilla block entities, plus several from Iron Chests, Iron Shulker Boxes, and Immersive Engineering prepopulate the whitelist.
  • A new config option under debug was added which disables the whitelist. This can be used to quickly test new blocks without needing to modify the tag to decide which entries to add to the tag.
  • Feel free to suggest further default whitelist entries on GitHub.
    • Note my requirements for whitelisting it are the inventory fully works in the crafting station UI.
    • This means you need to test it before suggesting it.
    • A notable case that I’ve seen commonly that doesn’t work is inventories with max stack size larger than 64, we cannot support that without special casing currently.

Fluid Outputs

Since 3.9.1
  • Mantle now supports fluids using the tag preference system in fluid outputs.
  • All recipes that output fluids now support fluid outputs instead, including melting byproducts.
  • In datapacks, a tag output can be specified by swapping fluid for tag.

Relevant new tags

Since 3.9.1

  • Fluid tag tconstruct:hide_in_creative_tanks will stop the fluid from appearing in a prefilled tank/copper can in JEI/creative. Prepopulated with c:hidden_from_recipe_viewers.

Resource Packs

Modifier Icon Stitching

Modifier icons no longer automatically stitch any texture path passed in. Minecraft will automatically stitch all sprites in textures/item and textures/block folders, and Tinkers’ Construct additionally adds textures/gui/modifiers for use with modifier icons. If you wish to place icons in any other directory you must stitch it using the atlas JSON.

Faucet Fluid moving

The JSON files for faucet fluids were moved from assets/<domain>/models/faucet_fluid/ to assets/<domain>/mantle/model/faucet_fluid/. See faucet fluids for more information.

Inventory and fluid model rework

Model JSON that defined fluids or items inside were removed in favor of new JSON directories. The following list describes their replacements:

In addition, if you were using the tconstruct:tank model, you will likely need to add a block fluid to ensure the block entity continues to render; the tconstruct:tank models purpose is now just rendering fluids in the model (which is more efficient for static fluids and less efficient for changing fluids).

The reason for this change was other modders deciding they need to recreate the Optifine CTM format on Fabric by wrapping every single baked model with their own class, then using Connector to work on Forge, we were forced to migrate away from loading data from JSON models. Plus, we have far better methods of data loading that have been added since those models were coded.

Modifier Slot Type Colors

Modifier slot type colors are now controlled using Mantle’s resource colors instead of a constructor paramter. They key for slot type <name> will be stat.tconstruct.slot.<name>.

Java

Loadable Context Propagation

The TypedMap context parameter from RecordLoadable is now passed through all layers of the Loadable parsing and can be passed to any JSON deserialize or buffer decode method. As a result of this change, you can pass in more advanced contexts to your parsing, such as registry access or client data lookups.

If you made use of raw Loadable or RecordLoadable instantiations, you may need to adjust your code to properly obtain the context parameter and pass it to children. If you only used RecordLoadable.create() or other builders, then you shouldn’t need any changes. Callers of the API only need to pass in context if they plan to use it; if not an empty context will be passed.

ArmorSlotType -> ArmorItem.Type

ArmorSlotType was an enum listing all 4 armor types (helmet, chestplate, leggings, and boots). In 1.20, Mojang created a nearly identical enum called ArmorItem.Type.

The main difference between these two enums is Mojang ordered the types top down (helmet to boots), while our original enum was bottom up (boots to helmet). Any loops using ArmorSlotType#TOP_DOWN can simply use ArmorItem.Type#values(), while if you need to loop in the other order that will require your own list.

The ordering notably affected SetStatsModule.ArmorBuilder#setEach as the constructor now receives slots in the opposite order (meaning using the default constructors you now list values top down instead of bottom up). To nudge addon authors of the change, we renamed the method to SetStatsModule.ArmorBuilder#setInOrder and updating the docs accordingly. Your JSON for your tool definition shouldn’t change when you run updated datagen.

Utilities under ArmorSlotType were relocated:

  • ArmorSlotType.ArmorBuilder -> ArmorModuleBuilder
  • ArmorSlotType.ArmorShieldBuilder -> ArmorModuleBuilder.ArmorShieldModuleBuilder
  • ArmorSlotType#MAX_DAMAGE_ARRAY -> ArmorModuleBuilder#MAX_DAMAGE_ARRAY, though indices are now top down instead of bottom up.
  • ArmorSlotType#SHIELD_DAMAGE -> ArmorModuleBuilder#SHIELD_DAMAGE.

Armor Texture Supplier

The armor texture supplier got reworked to better support armor trims. Instead of returning a ArmorTexture which contains a path to your texture and a tint, ArmorTexture is now an interface which contains a method to render your texture on the model.

The class TintedArmorTexture gives equivalent behavior to the 1.19 armor texture supplier return. Alternatively, you can implement your own texture supplier if you need more advanced behavior.

Tinker Station Lazy Tool Stack

Since 3.9.1
  • The tinker station recipe now returns RecipeResult<LazyToolStack> instead of RecipeResult<ItemStack>. This makes it easier to process tool stacks in ITinkerStationRecipe#updateInputs() and makes it more efficient as the NBT need not be parsed multiple times in the table UI.
  • To aid in creation of successful results, see LazyToolStack#success(), ITinkerStationRecipe#success(), or AbstractModifierRecipe#success() (based on the type of recipe you are working with).

ModDataNBT Cleanup

Since 3.9.1
  • ModDataNBT no longer long allows setting modifier slots, just reading them.
  • For usages that need to change modifier slots, ToolDataNBT must be used. This is only available to ToolStack and the volatile modifier hooks, not standard modifier hooks in persistent data.
  • NamespacedNBT was removed, all usages (projectile hooks, persistent data capability) now use ModDataNBT directly. Similarly INamespacedNBTView was removed in favor of IModDataView.

Class renames

  • TinkerTransformTypes was renamed to TinkerItemDisplays.
  • TinkerHooks was renamed earlier in 1.19 to ModifierHooks.
  • ModelItem was renamed to RenderItem

Class and method removals

  • RetexturedBlockItem/TableBlockItem were removed as they are no longer needed. Just use a standard BlockItem/TooltipBlockItem. All the block items did was creative tab filling which now exists outside the item instance.
  • Many classes had their friendly byte buffer read/write methods or their JSON serialize/deserialize methods removed. If that happened, they typically have a static field named LOADER or LOADABLE which can be used for those operations. Similarly, many methods from JsonUtils are removed as they have an equivalent in the Loadable API.
  • IGenericLoader was replaced by RecordLoadable. Methods are similar if you wish to implement it directly, or alternatively you can make use of Loadable API to build a RecordLoadable automatically.
  • FaucetFluidLoader is now located at FaucetFluid#REGISTRY, with some of its helper methods moved to RenderingHelper.
  • InventoryModifier and InventoryMenuModifier were replaced with InventoryModule and InventoryMenuModule.
  • Book command suggestions were removed as the book command is now a client command so it can just directly use the registry.

Modifiers:

  • AbstractWalkerModifier was replaced with ArmorWalkRadiusModule. You can implement that interface on a modifier or a module.
  • Many modifier fields were removed from TinkerModifiers, they are likely in ModifierIds

Fluid Object Tags

  • Fluid objects #getForgeTag() was renamed to #getCommonTag(). This method is also notably now nullable.
  • In the builder for a fluid object, calling commonTag() will add the default tag under forge: for the fluid. Calling commonTag(name) will set the common tag to a specific name (previous behavior).
  • Any objects with no call to either variant of commonTag() will have no common tag. This will cause relevant datagen helpers to use the local tag or the fluid directly.
  • To conveniently create an ingredient from the object, use FluidObject#ingredient(). This will automatically use the common tag if set, otherwise the local tag (for flowing objects) or the fluid itself (for non-flowing objects).
  • To conveniently create a reicpe result from the object, use FluidObject#result(). This will automatically use the common tag if set, otherwise the fluid itself.