24w10a porting fixes ()

* Rename mixin using unmapped name

* Fix potential crash in item API testmod

* Improve custom ingredient javadoc

* More javadoc improvements

* Add more tests

* whoops

* Fix typos

* Remove test for strict NBT matching

* another whoopsie

* Finish NBT -> components changes

Breaking change: `FabricItem#allowNbtUpdateAnimation` was renamed to
`allowComponentsUpdateAnimation`.

* Fix broken javadoc links

* Fix broken screen handler testmod
This commit is contained in:
apple502j 2024-03-12 18:22:55 +09:00 committed by GitHub
parent 031f0cf067
commit 42c290b4ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 128 additions and 87 deletions
fabric-content-registries-v0/src/main
java/net/fabricmc/fabric/mixin/content/registry
resources
fabric-data-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1
fabric-data-generation-api-v1/src
main/java/net/fabricmc/fabric/api/datagen/v1/provider
testmod/java/net/fabricmc/fabric/test/datagen
fabric-item-api-v1/src
client/java/net/fabricmc/fabric/mixin/item/client
main/java/net/fabricmc/fabric/api/item/v1
testmod/java/net/fabricmc/fabric/test/item
fabric-item-group-api-v1/src/main/java/net/fabricmc/fabric/api/itemgroup/v1
fabric-networking-api-v1/src
client/java/net/fabricmc/fabric/api/client/networking/v1
main/java/net/fabricmc/fabric/api/networking/v1
fabric-recipe-api-v1/src
main/java/net/fabricmc/fabric/api/recipe/v1/ingredient
testmod/java/net/fabricmc/fabric/test/recipe/ingredient
fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1
fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item
fabric-transfer-api-v1

View file

@ -32,19 +32,19 @@ import net.minecraft.world.CollisionView;
import net.fabricmc.fabric.api.registry.LandPathNodeTypesRegistry;
@Mixin(PathContext.class)
public abstract class class_9316Mixin {
public abstract class PathContextMixin {
@Shadow
public abstract BlockState method_57623(BlockPos blockPos);
public abstract BlockState getBlockState(BlockPos blockPos);
@Shadow
public abstract CollisionView method_57621();
public abstract CollisionView getWorld();
/**
* Overrides the node type for the specified position, if the position is found as neighbor block in a path.
*/
@Inject(method = "getNodeType", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/util/math/BlockPos$Mutable;set(III)Lnet/minecraft/util/math/BlockPos$Mutable;"), cancellable = true)
private void method_57622(int x, int y, int z, CallbackInfoReturnable<PathNodeType> cir, @Local BlockPos pos) {
final PathNodeType neighborNodeType = LandPathNodeTypesRegistry.getPathNodeType(method_57623(pos), method_57621(), pos, true);
private void onGetNodeType(int x, int y, int z, CallbackInfoReturnable<PathNodeType> cir, @Local BlockPos pos) {
final PathNodeType neighborNodeType = LandPathNodeTypesRegistry.getPathNodeType(getBlockState(pos), getWorld(), pos, true);
if (neighborNodeType != null) {
cir.setReturnValue(neighborNodeType);

View file

@ -4,7 +4,7 @@
"compatibilityLevel": "JAVA_17",
"mixins": [
"AxeItemAccessor",
"class_9316Mixin",
"PathContextMixin",
"FarmerWorkTaskAccessor",
"GiveGiftsToHeroTaskAccessor",
"HoeItemAccessor",

View file

@ -51,7 +51,7 @@ import net.minecraft.world.chunk.ChunkStatus;
* <p>
* Note about {@link BlockEntity} targets: by default, many block entities use their NBT to synchronize with the client.
* That would mean persistent attachments are automatically synced with the client for those block entities. As this is
* undesirable behavior, the API completely removes attachments from the result of {@link BlockEntity#toInitialChunkDataNbt()},
* undesirable behavior, the API completely removes attachments from the result of {@link BlockEntity#toInitialChunkDataNbt},
* which takes care of all vanilla types. However, modded block entities may be coded differently, so be wary of this
* when attaching data to modded block entities.
* </p>

View file

@ -52,8 +52,8 @@ import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
/**
* Extend this class and implement {@link FabricLanguageProvider#generateTranslations(TranslationBuilder)}.
* Make sure to use {@link FabricLanguageProvider#FabricLanguageProvider(FabricDataOutput, String, CompletableFuture)} FabricLanguageProvider} to declare what language code is being generated if it isn't {@code en_us}.
* Extend this class and implement {@link FabricLanguageProvider#generateTranslations}.
* Make sure to use {@link FabricLanguageProvider#FabricLanguageProvider(FabricDataOutput, String, CompletableFuture) FabricLanguageProvider} to declare what language code is being generated if it isn't {@code en_us}.
*
* <p>Register an instance of the class with {@link FabricDataGenerator.Pack#addProvider} in a {@link net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint}.
*/
@ -117,7 +117,7 @@ public abstract class FabricLanguageProvider implements DataProvider {
}
/**
* A consumer used by {@link FabricLanguageProvider#generateTranslations(TranslationBuilder)}.
* A consumer used by {@link FabricLanguageProvider#generateTranslations}.
*/
@ApiStatus.NonExtendable
@FunctionalInterface

View file

@ -53,7 +53,6 @@ import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
@ -189,7 +188,7 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
// - 9 damaged pickaxes should not match.
// - 9 undamaged pickaxes should match.
// - 1 undamaged pickaxe + 8 damaged pickaxes should match (regardless of the position).
// - 1 undamaged renamed pickaxe + 8 damaged pickaxes should match (NBT is not strictly matched here).
// - 1 undamaged renamed pickaxe + 8 damaged pickaxes should match (components are not strictly matched here).
ShapelessRecipeJsonBuilder.create(RecipeCategory.MISC, Items.DIAMOND_BLOCK)
.input(Ingredient.ofItems(Items.DIAMOND_PICKAXE))
.input(Ingredient.ofItems(Items.DIAMOND_PICKAXE))
@ -209,17 +208,6 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
.criterion("has_pickaxe", conditionsFromItem(Items.DIAMOND_PICKAXE))
.offerTo(exporter);
// Test strict NBT
// To test: try renaming an apple to "Golden Apple" in creative with an anvil.
// That should match the recipe and give a golden apple. Any other NBT should not match.
ItemStack appleWithGoldenName = new ItemStack(Items.APPLE);
appleWithGoldenName.set(DataComponentTypes.CUSTOM_NAME, Text.literal("Golden Apple"));
appleWithGoldenName.set(DataComponentTypes.REPAIR_COST, 0);
ShapelessRecipeJsonBuilder.create(RecipeCategory.MISC, Items.GOLDEN_APPLE)
.input(DefaultCustomIngredients.components(appleWithGoldenName))
.criterion("has_apple", conditionsFromItem(Items.APPLE))
.offerTo(exporter);
// Test AND
// To test: charcoal should give a torch, but coal should not.
ShapelessRecipeJsonBuilder.create(RecipeCategory.MISC, Items.TORCH)

View file

@ -31,7 +31,7 @@ import net.minecraft.util.Hand;
import net.fabricmc.fabric.api.item.v1.FabricItem;
/**
* Allow canceling the held item update animation if {@link FabricItem#allowNbtUpdateAnimation} returns false.
* Allow canceling the held item update animation if {@link FabricItem#allowComponentsUpdateAnimation} returns false.
*/
@Mixin(HeldItemRenderer.class)
public class HeldItemRendererMixin {
@ -51,7 +51,7 @@ public class HeldItemRendererMixin {
ItemStack newMainStack = client.player.getMainHandStack();
if (mainHand.getItem() == newMainStack.getItem()) {
if (!mainHand.getItem().allowNbtUpdateAnimation(client.player, Hand.MAIN_HAND, mainHand, newMainStack)) {
if (!mainHand.getItem().allowComponentsUpdateAnimation(client.player, Hand.MAIN_HAND, mainHand, newMainStack)) {
mainHand = newMainStack;
}
}
@ -60,7 +60,7 @@ public class HeldItemRendererMixin {
ItemStack newOffStack = client.player.getOffHandStack();
if (offHand.getItem() == newOffStack.getItem()) {
if (!offHand.getItem().allowNbtUpdateAnimation(client.player, Hand.OFF_HAND, offHand, newOffStack)) {
if (!offHand.getItem().allowComponentsUpdateAnimation(client.player, Hand.OFF_HAND, offHand, newOffStack)) {
offHand = newOffStack;
}
}

View file

@ -42,8 +42,8 @@ import net.fabricmc.fabric.impl.item.FabricItemInternals;
*/
public interface FabricItem {
/**
* When the NBT of an item stack in the main hand or off hand changes, vanilla runs an "update animation".
* This function is called on the client side when the NBT or count of the stack has changed, but not the item,
* When the components of an item stack in the main hand or off hand changes, vanilla runs an "update animation".
* This function is called on the client side when the components or count of the stack has changed, but not the item,
* and returning false cancels this animation.
*
* @param player the current player; this may be safely cast to {@link net.minecraft.client.network.ClientPlayerEntity} in client-only code
@ -52,13 +52,13 @@ public interface FabricItem {
* @param newStack the new stack, also of this item
* @return true to run the vanilla animation, false to cancel it.
*/
default boolean allowNbtUpdateAnimation(PlayerEntity player, Hand hand, ItemStack oldStack, ItemStack newStack) {
default boolean allowComponentsUpdateAnimation(PlayerEntity player, Hand hand, ItemStack oldStack, ItemStack newStack) {
return true;
}
/**
* When the NBT of the selected stack changes, block breaking progress is reset.
* This function is called when the NBT of the selected stack has changed,
* When the components of the selected stack changes, block breaking progress is reset.
* This function is called when the components of the selected stack has changed,
* and returning true allows the block breaking progress to continue.
*
* @param player the player breaking the block

View file

@ -52,7 +52,7 @@ public class CustomDamageTest implements ModInitializer {
if (entity.isSneaking()) {
return amount;
} else {
stack.set(WEIRD, stack.getOrDefault(WEIRD, 0) + 1);
stack.set(WEIRD, Math.max(0, stack.getOrDefault(WEIRD, 0) + 1));
return 0;
}
};

View file

@ -46,12 +46,12 @@ public class UpdatingItem extends Item {
@Override
public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) {
if (!world.isClient) {
stack.set(ItemUpdateAnimationTest.TICKS, stack.getOrDefault(ItemUpdateAnimationTest.TICKS, 0) + 1);
stack.set(ItemUpdateAnimationTest.TICKS, Math.max(0, stack.getOrDefault(ItemUpdateAnimationTest.TICKS, 0) + 1));
}
}
@Override
public boolean allowNbtUpdateAnimation(PlayerEntity player, Hand hand, ItemStack originalStack, ItemStack updatedStack) {
public boolean allowComponentsUpdateAnimation(PlayerEntity player, Hand hand, ItemStack originalStack, ItemStack updatedStack) {
return allowUpdateAnimation;
}

View file

@ -214,7 +214,7 @@ public class FabricItemGroupEntries implements ItemGroup.Entries {
/**
* Adds stacks after an existing stack in the group, or at the end, if the stack isn't in the group.
*
* @param afterLast Add {@code newStacks} after the last group entry matching this stack (compared using {@link ItemStack#areItemsAndNbtEqual}).
* @param afterLast Add {@code newStacks} after the last group entry matching this stack (compared using {@link ItemStack#areItemsAndComponentsEqual}).
* @param newStacks The stacks to add. Only {@linkplain #isEnabled(ItemStack) enabled} stacks will be added.
* @param visibility Determines whether the stack will be shown in the tab itself, returned
* for searches, or both.
@ -331,7 +331,7 @@ public class FabricItemGroupEntries implements ItemGroup.Entries {
/**
* Adds stacks before an existing stack to the group, or at the end, if the stack isn't in the group.
*
* @param beforeFirst Add {@code newStacks} before the first group entry matching this stack (compared using {@link ItemStack#areItemsAndNbtEqual}).
* @param beforeFirst Add {@code newStacks} before the first group entry matching this stack (compared using {@link ItemStack#areItemsAndComponentsEqual}).
* @param newStacks The stacks to add. Only {@linkplain #isEnabled(ItemStack) enabled} stacks will be added.
* @param visibility Determines whether the stack will be shown in the tab itself, returned
* for searches, or both.

View file

@ -18,7 +18,7 @@ package net.fabricmc.fabric.api.client.networking.v1;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientConfigurationNetworkHandler;
import net.minecraft.util.Identifier;
import net.minecraft.network.packet.CustomPayload;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
@ -30,7 +30,7 @@ public final class ClientConfigurationConnectionEvents {
/**
* Event indicating a connection entering the CONFIGURATION state, ready for registering channel handlers.
*
* @see ClientConfigurationNetworking#registerReceiver(Identifier, ClientConfigurationNetworking.ConfigurationChannelHandler)
* @see ClientConfigurationNetworking#registerReceiver(CustomPayload.Id, ClientConfigurationNetworking.ConfigurationPayloadHandler)
*/
public static final Event<ClientConfigurationConnectionEvents.Init> INIT = EventFactory.createArrayBacked(ClientConfigurationConnectionEvents.Init.class, callbacks -> (handler, client) -> {
for (ClientConfigurationConnectionEvents.Init callback : callbacks) {

View file

@ -18,7 +18,7 @@ package net.fabricmc.fabric.api.client.networking.v1;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.util.Identifier;
import net.minecraft.network.packet.CustomPayload;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
@ -31,7 +31,7 @@ public final class ClientPlayConnectionEvents {
/**
* Event indicating a connection entered the PLAY state, ready for registering channel handlers.
*
* @see ClientPlayNetworking#registerReceiver(Identifier, ClientPlayNetworking.PlayChannelHandler)
* @see ClientPlayNetworking#registerReceiver(CustomPayload.Id, ClientPlayNetworking.PlayPayloadHandler)
*/
public static final Event<Init> INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, client) -> {
for (Init callback : callbacks) {

View file

@ -16,9 +16,9 @@
package net.fabricmc.fabric.api.networking.v1;
import net.minecraft.network.packet.CustomPayload;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
@ -30,7 +30,7 @@ public final class ServerPlayConnectionEvents {
/**
* Event indicating a connection entered the PLAY state, ready for registering channel handlers.
*
* @see ServerPlayNetworking#registerReceiver(ServerPlayNetworkHandler, Identifier, ServerPlayNetworking.PlayChannelHandler)
* @see ServerPlayNetworking#registerReceiver(ServerPlayNetworkHandler, CustomPayload.Id, ServerPlayNetworking.PlayPayloadHandler)
*/
public static final Event<Init> INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, server) -> {
for (Init callback : callbacks) {

View file

@ -102,10 +102,21 @@ public final class DefaultCustomIngredients {
* Creates an ingredient that wraps another ingredient to also check for matching components.
*
* <p>Use {@link ComponentChanges#builder()} to add or remove components.
* Added components are checked to match on the target stack.
* Removed components are checked to not exist in the target stack
* Added components are checked to match on the target stack, either as the default or
* the item stack-specific override.
* Removed components are checked to not exist in the target stack.
* The check is "non-strict"; components that are neither added nor removed are ignored.
*
* @throws IllegalArgumentException if {@link ComponentChanges#isEmpty} is true
* <p>The JSON format is as follows:
* <pre>{@code
* {
* "fabric:type": "fabric:components",
* "base": // base ingredient,
* "components": // components to be checked
* }
* }</pre>
*
* @throws IllegalArgumentException if there are no components to check
*/
public static Ingredient components(Ingredient base, ComponentChanges components) {
Objects.requireNonNull(base, "Base ingredient cannot be null");
@ -122,10 +133,17 @@ public final class DefaultCustomIngredients {
}
/**
* Creates an ingredient that matches the passed template stack, including {@link ItemStack#getComponentChanges()}.
* Creates an ingredient that matches the components specified in the passed item stack.
* Note that the count of the stack is ignored.
*
* <p>This does not check for the default component of the item stack that remains unchanged.
* For example, an undamaged pickaxe matches any pickaxes (regardless of damage), because having
* zero damage is the default, but a pickaxe with 1 damage would only match another pickaxe
* with 1 damage. To only match the default value, use the other methods and explicitly specify
* the default value.
*
* @see #components(Ingredient, ComponentChanges)
* @throws IllegalArgumentException if {@code stack} has no changed components
*/
public static Ingredient components(ItemStack stack) {
Objects.requireNonNull(stack, "Stack cannot be null");

View file

@ -20,8 +20,10 @@ import java.util.Objects;
import net.minecraft.component.ComponentChanges;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.NbtComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.recipe.Ingredient;
import net.minecraft.test.GameTest;
import net.minecraft.test.GameTestException;
@ -90,7 +92,7 @@ public class IngredientMatchTests {
@GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE)
public void testComponentIngredient(TestContext context) {
final Ingredient baseIngredient = Ingredient.ofItems(Items.DIAMOND_PICKAXE, Items.NETHERITE_PICKAXE);
final Ingredient baseIngredient = Ingredient.ofItems(Items.DIAMOND_PICKAXE, Items.NETHERITE_PICKAXE, Items.STICK);
final Ingredient undamagedIngredient = DefaultCustomIngredients.components(
baseIngredient,
builder -> builder.add(DataComponentTypes.DAMAGE, 0)
@ -107,7 +109,7 @@ public class IngredientMatchTests {
assertEquals(true, undamagedIngredient.test(renamedUndamagedDiamondPickaxe));
assertEquals(false, noNameUndamagedIngredient.test(renamedUndamagedDiamondPickaxe));
assertEquals(2, undamagedIngredient.getMatchingStacks().length);
assertEquals(3, undamagedIngredient.getMatchingStacks().length);
ItemStack result0 = undamagedIngredient.getMatchingStacks()[0];
ItemStack result1 = undamagedIngredient.getMatchingStacks()[1];
@ -126,6 +128,33 @@ public class IngredientMatchTests {
damagedDiamondPickaxe.setDamage(10);
assertEquals(false, undamagedIngredient.test(damagedDiamondPickaxe));
// Checking for DAMAGE component requires the item is damageable in the first place
assertEquals(false, undamagedIngredient.test(new ItemStack(Items.STICK)));
// Custom data is strictly matched, like any other component with multiple fields
final NbtCompound requiredData = new NbtCompound();
requiredData.putInt("keyA", 1);
final NbtCompound extraData = requiredData.copy();
extraData.putInt("keyB", 2);
final Ingredient customDataIngredient = DefaultCustomIngredients.components(
baseIngredient,
builder -> builder.add(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(requiredData))
);
ItemStack requiredDataStack = new ItemStack(Items.DIAMOND_PICKAXE);
requiredDataStack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(requiredData));
ItemStack extraDataStack = new ItemStack(Items.DIAMOND_PICKAXE);
extraDataStack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraData));
assertEquals(true, customDataIngredient.test(requiredDataStack));
assertEquals(false, customDataIngredient.test(extraDataStack));
// Default value is ignored in components(ItemStack)
final Ingredient damagedPickaxeIngredient = DefaultCustomIngredients.components(renamedUndamagedDiamondPickaxe);
ItemStack renamedDamagedDiamondPickaxe = renamedUndamagedDiamondPickaxe.copy();
renamedDamagedDiamondPickaxe.setDamage(10);
assertEquals(true, damagedPickaxeIngredient.test(renamedUndamagedDiamondPickaxe));
assertEquals(true, damagedPickaxeIngredient.test(renamedDamagedDiamondPickaxe));
context.complete();
}

View file

@ -35,7 +35,7 @@ import net.minecraft.util.profiler.Profiler;
/**
* Except as noted below, the properties exposed here match the parameters passed to
* {@link WorldRenderer#render(MatrixStack, float, long, boolean, Camera, GameRenderer, LightmapTextureManager, Matrix4f)}.
* {@link WorldRenderer#render}.
*/
public interface WorldRenderContext {
/**

View file

@ -19,6 +19,7 @@ package net.fabricmc.fabric.api.client.rendering.v1;
import org.jetbrains.annotations.Nullable;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.util.hit.HitResult;
@ -27,7 +28,7 @@ import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* Mods should use these events to introduce custom rendering during {@link WorldRenderer#render(net.minecraft.client.util.math.MatrixStack, float, long, boolean, net.minecraft.client.render.Camera, net.minecraft.client.render.GameRenderer, net.minecraft.client.render.LightmapTextureManager, net.minecraft.util.math.Matrix4f)}
* Mods should use these events to introduce custom rendering during {@link WorldRenderer#render}
* without adding complicated and conflict-prone injections there. Using these events also enables 3rd-party renderers
* that make large-scale changes to rendering maintain compatibility by calling any broken event invokers directly.
*
@ -107,7 +108,7 @@ public final class WorldRenderEvents {
*
* <p>Use for global block entity render setup, or
* to append block-related quads to the entity consumers using the
* {@VertexConsumerProvider} from the provided context. This
* {@link VertexConsumerProvider} from the provided context. This
* will generally give better (if not perfect) results
* for non-terrain translucency vs. drawing directly later on.
*/

View file

@ -27,7 +27,9 @@ final class BagInventory implements ImplementedInventory {
BagInventory(ItemStack stack) {
this.stack = stack;
stack.getOrDefault(DataComponentTypes.CONTAINER, ContainerComponent.fromStacks(items));
ContainerComponent container = stack.get(DataComponentTypes.CONTAINER);
if (container != null) container.copyTo(items);
}
@Override

View file

@ -23,7 +23,7 @@ and combine them with `CombinedStorage`.
## Fluid transfer
A `Storage<FluidVariant>` is any object that can store fluids. It is just a `Storage<T>`, where `T` is
[`FluidVariant`](src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidVariant.java), the immutable combination of a `Fluid` and additional NBT data.
[`FluidVariant`](src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidVariant.java), the immutable combination of a `Fluid` and additional components.
Instances can be accessed through the API lookups defined in [`FluidStorage`](src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidStorage.java).
The unit for fluid transfer is 1/81000ths of a bucket, also known as _droplets_.
@ -31,8 +31,8 @@ The unit for fluid transfer is 1/81000ths of a bucket, also known as _droplets_.
to work with droplets.
Client-side [Fluid variant rendering](src/main/java/net/fabricmc/fabric/api/transfer/v1/client/fluid/FluidVariantRendering.java) will use regular fluid rendering by default,
ignoring the additional NBT data.
`Fluid`s that wish to render differently depending on the stored NBT data can register a
ignoring the additional components.
`Fluid`s that wish to render differently depending on the stored components can register a
[`FluidVariantRenderHandler`](src/main/java/net/fabricmc/fabric/api/transfer/v1/client/fluid/FluidVariantRenderHandler.java).
## Item transfer

View file

@ -39,7 +39,7 @@ import net.fabricmc.fabric.impl.transfer.fluid.CauldronStorage;
* <p>The {@code CauldronFluidContent} itself defines:
* <ul>
* <li>The block of the cauldron.</li>
* <li>The fluid that can be accepted by the cauldron. NBT is discarded when entering the cauldron.</li>
* <li>The fluid that can be accepted by the cauldron. Components are discarded when entering the cauldron.</li>
* <li>Which fluid amounts can be stored in the cauldron, and how they map to the level property of the cauldron.
* If {@code levelProperty} is {@code null}, then {@code maxLevel = 1}, and there is only one level.
* Otherwise, the levels are all the integer values between {@code 1} and {@code maxLevel} (included).

View file

@ -35,7 +35,7 @@ import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
/**
* Base implementation of a fluid storage for an empty item.
* The empty item can be filled with an exact amount of some fluid to yield a full item instead.
* The default behavior is to copy the NBT from the empty item to the full item,
* The default behavior is to copy the components from the empty item to the full item,
* however there is a second constructor that allows customizing the mapping.
*
* <p>For example, an empty bucket could be registered to accept exactly 81000 droplets of water and turn into a water bucket, like that:
@ -67,7 +67,7 @@ public final class EmptyItemFluidStorage implements InsertionOnlyStorage<FluidVa
*
* @param context The current context.
* @param fullItem The new item after a successful fill operation.
* @param insertableFluid The fluid that can be inserted. Fluid variant NBT is ignored.
* @param insertableFluid The fluid that can be inserted. Fluid variant components are ignored.
* @param insertableAmount The amount of fluid that can be inserted.
*/
public EmptyItemFluidStorage(ContainerItemContext context, Item fullItem, Fluid insertableFluid, long insertableAmount) {
@ -76,12 +76,12 @@ public final class EmptyItemFluidStorage implements InsertionOnlyStorage<FluidVa
/**
* Create a new instance, with a custom mapping function.
* The mapping function allows customizing how the NBT of the full item depends on the NBT of the empty item.
* The default behavior with the other constructor is to just copy the full NBT.
* The mapping function allows customizing how the components of the full item depends on the components of the empty item.
* The default behavior with the other constructor is to just copy the full components.
*
* @param context The current context.
* @param emptyToFullMapping A function mapping the empty item variant, to the variant that should be used for the full item.
* @param insertableFluid The fluid that can be inserted. Fluid variant NBT is ignored on insertion.
* @param insertableFluid The fluid that can be inserted. Fluid variant components are ignored on insertion.
* @param insertableAmount The amount of fluid that can be inserted.
* @see #EmptyItemFluidStorage(ContainerItemContext, Item, Fluid, long)
*/

View file

@ -31,7 +31,7 @@ import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
/**
* Base implementation of a fluid storage for a full item.
* The full item contains some fixed amount of a fluid variant, which can be extracted entirely to yield an empty item.
* The default behavior is to copy the NBT from the full item to the empty item,
* The default behavior is to copy the components from the full item to the empty item,
* however there is a second constructor that allows customizing the mapping.
*
* <p>This is used similarly to {@link EmptyItemFluidStorage}.
@ -57,8 +57,8 @@ public final class FullItemFluidStorage implements ExtractionOnlyStorage<FluidVa
/**
* Create a new instance, with a custom mapping function.
* The mapping function allows customizing how the NBT of the empty item depends on the NBT of the full item.
* The default behavior with the other constructor is to just copy the full NBT.
* The mapping function allows customizing how the components of the empty item depends on the components of the full item.
* The default behavior with the other constructor is to just copy the full components.
*
* @param context The current context.
* @param fullToEmptyMapping A function mapping the full item variant, to the variant that should be used

View file

@ -45,7 +45,7 @@
*
* <p><h2>Fluid transfer</h2>
* A {@code Storage<FluidVariant>} is any object that can store fluids. It is just a {@code Storage<T>}, where {@code T} is
* {@link net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant FluidVariant}, the immutable combination of a {@code Fluid} and additional NBT data.
* {@link net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant FluidVariant}, the immutable combination of a {@code Fluid} and additional components.
* Instances can be accessed through the API lookups defined in {@link net.fabricmc.fabric.api.transfer.v1.fluid.FluidStorage FluidStorage}.
* </p>
*
@ -53,8 +53,8 @@
* {@link net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants FluidConstants} contains a few helpful constants to work with droplets.
*
* <p>Client-side {@linkplain net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRendering fluid variant rendering} will use regular fluid rendering by default,
* ignoring the additional NBT data.
* {@code Fluid}s that wish to render differently depending on the stored NBT data can register a
* ignoring the additional components.
* {@code Fluid}s that wish to render differently depending on the stored components can register a
* {@link net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRenderHandler FluidVariantRenderHandler}.
*
* <p><h2>Item transfer</h2>

View file

@ -27,7 +27,7 @@ import net.minecraft.component.ComponentChanges;
* but note that a {@link Storage} is not necessarily bound to {@code TransferVariant}. Its generic parameter can be any immutable object.
*
* <p><b>Transfer variants must always be compared with {@code equals}, never by reference!</b>
* {@code hashCode} is guaranteed to be correct and constant time independently of the size of the NBT.
* {@code hashCode} is guaranteed to be correct and constant time independently of the size of the components.
*
* @param <O> The type of the immutable object instance, for example {@code Item} or {@code Fluid}.
*/

View file

@ -27,7 +27,7 @@ import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
/**
* Base implementation of a fixed-capacity "continuous" storage for item-provided storage APIs.
* The item may not change, so the data has to be stored in the NBT of the stacks.
* The item may not change, so the data has to be stored in the components of the stacks.
* This can be used for example to implement portable fluid tanks, fluid-containing jetpacks, and so on...
* Continuous here means that they can store any integer amount between 0 and the capacity, unlike buckets or bottles.
*
@ -35,11 +35,11 @@ import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
* <ul>
* <li>You must override {@link #getBlankResource()}, for example {@code return FluidVariant.blank();} for fluids.</li>
* <li>You must override {@link #getResource(ItemVariant)} and {@link #getAmount(ItemVariant)}.
* Generally you will read the resource and the amount from the NBT of the item variant.</li>
* Generally you will read the resource and the amount from the components of the item variant.</li>
* <li>You must override {@link #getCapacity(TransferVariant)} to set the capacity of your storage.</li>
* <li>You must override {@link #getUpdatedVariant}. It is used to change the resource and the amount of the item variant.
* Generally you will copy the NBT, modify it, and then create a new variant from that.
* Copying the NBT instead of recreating it from scratch is important to keep custom names or enchantments.</li>
* Generally you will copy the components, modify it, and then create a new variant from that.
* Copying the components instead of recreating it from scratch is important to keep custom names or enchantments.</li>
* <li>You may also override {@link #canInsert} and {@link #canExtract} if you want to restrict insertion and/or extraction.</li>
* </ul>
*
@ -66,12 +66,12 @@ public abstract class SingleVariantItemStorage<T extends TransferVariant<?>> imp
protected abstract T getBlankResource();
/**
* Return the current resource by reading the NBT of the passed variant.
* Return the current resource by reading the components of the passed variant.
*/
protected abstract T getResource(ItemVariant currentVariant);
/**
* Return the current amount by reading the NBT of the passed variant.
* Return the current amount by reading the components of the passed variant.
*/
protected abstract long getAmount(ItemVariant currentVariant);
@ -84,11 +84,12 @@ public abstract class SingleVariantItemStorage<T extends TransferVariant<?>> imp
/**
* Return an updated variant with new resource and amount.
* Implementors should generally convert the passed {@code currentVariant} to a stack,
* then edit the NBT of the stack so it contains the correct resource and amount.
* then edit the components of the stack so it contains the correct resource and amount.
*
* <p>When the new amount is 0, it is recommended that the sub-NBTs corresponding to the resource and amount
* be removed, for example using {@link ItemStack#removeSubNbt}, so that newly-crafted containers can stack with
* emptied containers.
* <p>When the new amount is 0, it is recommended that the components corresponding to the resource and amount
* be removed, so that newly-crafted containers can stack with emptied containers.
* If a custom item is used, this means {@linkplain ItemStack#set setting} it to the default as specified in {@link Item.Settings#component};
* if a vanilla item is used, this means {@linkplain ItemStack#remove removing} the said component.
*
* @param currentVariant Variant to which the modification should be applied.
* @param newResource Resource that should be contained in the returned variant.

View file

@ -189,7 +189,7 @@ class FluidItemTests extends AbstractTransferApiTest {
null,
StorageUtil.findExtractableContent(
ContainerItemContext.withConstant(new ItemStack(Items.WATER_BUCKET)).find(FluidStorage.ITEM),
FluidVariant::hasComponents, // Only allow NBT -> won't match anything.
FluidVariant::hasComponents, // Only allow components -> won't match anything.
null
)
);

View file

@ -90,7 +90,7 @@ class ItemTests extends AbstractTransferApiTest {
if (stack != inv.getStack(0)) throw new AssertionError("Stack should have stayed the same.");
// Also edit the stack when the item matches, even when the NBT and the count change.
// Also edit the stack when the item matches, even when the components and the count change.
ItemVariant oldVariant = ItemVariant.of(Items.DIAMOND);
ComponentChanges components = ComponentChanges.builder().add(ENERGY, 42).build();
ItemVariant newVariant = ItemVariant.of(Items.DIAMOND, components);
@ -102,7 +102,7 @@ class ItemTests extends AbstractTransferApiTest {
}
if (stack != inv.getStack(0)) throw new AssertionError("Stack should have stayed the same.");
if (!stackEquals(stack, newVariant, 5)) throw new AssertionError("Failed to update stack NBT or count.");
if (!stackEquals(stack, newVariant, 5)) throw new AssertionError("Failed to update stack components or count.");
}
@Test

View file

@ -45,7 +45,7 @@ public class PlayerInventoryStorageTests extends AbstractTransferApiTest {
}
@Test
public void testStackingInser() {
public void testStackingInsert() {
// Also test that the behavior of insert matches that of offer.
testStacking(playerInv -> playerInv::insert);
}
@ -69,14 +69,14 @@ public class PlayerInventoryStorageTests extends AbstractTransferApiTest {
try (Transaction tx = Transaction.openOuter()) {
assertEquals(1L, inserter.insert(stone, 1, tx));
// Should have went into the main stack
// Should have gone into the main stack
assertEquals(64, inv.main.get(3).getCount());
}
try (Transaction tx = Transaction.openOuter()) {
assertEquals(2L, inserter.insert(stone, 2, tx));
// Should have went into the main and offhand stacks.
// Should have gone into the main and offhand stacks.
assertEquals(64, inv.main.get(3).getCount());
assertEquals(63, inv.offHand.get(0).getCount());
}

View file

@ -97,7 +97,7 @@ public class SingleVariantItemStorageTests extends AbstractTransferApiTest {
tx.commit();
}
// Make sure custom NBT is kept.
// Make sure other components are kept.
Text customName = Text.literal("Lava-containing diamond!");
inv.getStack(0).set(DataComponentTypes.CUSTOM_NAME, customName);
@ -215,7 +215,9 @@ public class SingleVariantItemStorageTests extends AbstractTransferApiTest {
FluidData fluidData = new FluidData(newResource, newAmount);
stack.set(FLUID, fluidData);
} else {
// Make sure emptied tanks can stack with tanks without NBT.
// Make sure emptied tanks can stack with tanks without components.
// Note: because we use a vanilla item (diamond), we need to remove;
// a custom item should instead set the fluid to the default value as specified in the item settings.
stack.remove(FLUID);
}
}
@ -258,7 +260,7 @@ public class SingleVariantItemStorageTests extends AbstractTransferApiTest {
@Override
protected ItemVariant getUpdatedVariant(ItemVariant currentVariant, FluidVariant newResource, long newAmount) {
// Operate on the stack directly to keep any other NBT data such as a custom name or enchant.
// Operate on the stack directly to keep any other components such as a custom name or enchant.
ItemStack stack = currentVariant.toStack();
setContents(stack, newResource, newAmount);
return ItemVariant.of(stack);