Written by MerchantPug 12/16/2023
Disclaimer: This migration guide is provided in Yarn mappings, if you're using different mappings and don't know what any of these are, I'd recommend looking up your mappings using Linkie
If you are making a datapack, this change exclusively is an internal one, you should not have to change anything about your datapack for it to function with this. If there is any incorrect behaviour as a result of this rewrite though, you're best to report it here.
If you're an addon dev, this change might affect you, as any code that references Item Actions will need to be updated.
- Replace the type of direct Item Action references (
Pair<World, ItemStack>
) withPair<World, StackReference>
. - If you are registering any Item Actions, use the new
ItemActionFactory
class. In most cases,ItemActionFactory#createItemStackBased
should work just fine. If you need to replace the stack's item with a different item, use the default constructor. - Some of your item action code may need re-adjusting to fit
StackReference
s,InventoryUtil
has a few extra helper methods for gettingStackReference
s.
That's it. If you have any questions, feel free to talk in the Origins Discord's #addon-dev
channel, I won't be there, so if you wish to reach out to me specifically regarding this change, please DM me on Discord, @merchantpug
.
Apoli had a memory leak issue due to poor etiquite code that was used for Modify Enchantment Level and allowing certain actions to run on empty ItemStacks, this code basically caused a cache map to be bloated up with values, values which didn't remove upon entities being removed.
We felt that the best route was to rewrite item actions to use StackReference instead of ItemStack for two main reasons.
- It was a vanilla way of supporting setting items in an entity's inventory.
- We could deprecate the
MutableItemStack
interface, of which potentially caused issues with content where a stack's item type is used and is being cached, such as the Fabric Item Lookup API in some cases.
StackReference
s are pretty much how inventories can reference a slot with an item in them, and then replace that slot. It consists of two methods get
and set
, with both having custom implementation defined by the instance of the class.
For example, you may use StackReference#of(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/entity/EquipmentSlot;)
to get and set the specified entity's item in the specified equipment slot.
Another example would be InventoryUtil#createStackReference
, where it will basically hold a copy of the specified ItemStack, of which you are free to modify and use in other StackReference based code.
"Workable" empty ItemStacks are now only set through the modify_enchantment_level
power type, or if the StackReference that's currently being worked on within an item action currently holds an empty ItemStack, they are then replaced with the global ItemStack#EMPTY
once the entity has no modify_enchantment_level
powers, or if the item action returns an empty stack.