diff --git a/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/item/PlayerInventoryStorage.java b/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/item/PlayerInventoryStorage.java index ef2d7a77c..87da3927f 100644 --- a/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/item/PlayerInventoryStorage.java +++ b/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/item/PlayerInventoryStorage.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.ApiStatus; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.util.Hand; @@ -110,15 +111,47 @@ public interface PlayerInventoryStorage extends InventoryStorage { long offer(ItemVariant variant, long maxAmount, TransactionContext transaction); /** - * Drop items in the world at the player's location. + * Throw items in the world from the player's location. + * + *

Note: This function has full transaction support, and will not actually drop the items until the outermost transaction is committed. + * + * @param variant The variant to drop. + * @param amount How many of the variant to drop. + * @param throwRandomly If true, the variant will be thrown in a random direction from the entity regardless of which direction the entity is facing. + * @param retainOwnership If true, set the {@code Thrower} NBT data to the player's UUID. + * @param transaction The transaction this operation is part of. + * @see PlayerEntity#dropItem(ItemStack, boolean, boolean) + */ + void drop(ItemVariant variant, long amount, boolean throwRandomly, boolean retainOwnership, TransactionContext transaction); + + /** + * Throw items in the world from the player's location. + * + *

Note: This function has full transaction support, and will not actually drop the items until the outermost transaction is committed. + * + * @param variant The variant to drop. + * @param amount How many of the variant to drop. + * @param retainOwnership If true, set the {@code Thrower} NBT data to the player's UUID. + * @param transaction The transaction this operation is part of. + * @see PlayerEntity#dropItem(ItemStack, boolean, boolean) + */ + default void drop(ItemVariant variant, long amount, boolean retainOwnership, TransactionContext transaction) { + drop(variant, amount, false, retainOwnership, transaction); + } + + /** + * Throw items in the world from the player's location. * *

Note: This function has full transaction support, and will not actually drop the items until the outermost transaction is committed. * * @param variant The variant to drop. * @param amount How many of the variant to drop. * @param transaction The transaction this operation is part of. + * @see PlayerEntity#dropItem(ItemStack, boolean, boolean) */ - void drop(ItemVariant variant, long amount, TransactionContext transaction); + default void drop(ItemVariant variant, long amount, TransactionContext transaction) { + drop(variant, amount, false, transaction); + } /** * Return a wrapper around the current slot of the passed hand. diff --git a/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/item/PlayerInventoryStorageImpl.java b/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/item/PlayerInventoryStorageImpl.java index be700e453..79d305318 100644 --- a/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/item/PlayerInventoryStorageImpl.java +++ b/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/item/PlayerInventoryStorageImpl.java @@ -71,13 +71,13 @@ class PlayerInventoryStorageImpl extends InventoryStorageImpl implements PlayerI } @Override - public void drop(ItemVariant resource, long amount, TransactionContext tx) { - StoragePreconditions.notBlankNotNegative(resource, amount); + public void drop(ItemVariant variant, long amount, boolean throwRandomly, boolean retainOwnership, TransactionContext transaction) { + StoragePreconditions.notBlankNotNegative(variant, amount); // Drop in the world on the server side (will be synced by the game with the client). // Dropping items is server-side only because it involves randomness. if (amount > 0 && !playerInventory.player.world.isClient()) { - droppedStacks.addDrop(resource, amount, tx); + droppedStacks.addDrop(variant, amount, throwRandomly, retainOwnership, transaction); } } @@ -97,18 +97,16 @@ class PlayerInventoryStorageImpl extends InventoryStorageImpl implements PlayerI } private class DroppedStacks extends SnapshotParticipant { - final List droppedKeys = new ArrayList<>(); - final List droppedCounts = new ArrayList<>(); + final List entries = new ArrayList<>(); - void addDrop(ItemVariant key, long count, TransactionContext transaction) { + void addDrop(ItemVariant key, long amount, boolean throwRandomly, boolean retainOwnership, TransactionContext transaction) { updateSnapshots(transaction); - droppedKeys.add(key); - droppedCounts.add(count); + entries.add(new Entry(key, amount, throwRandomly, retainOwnership)); } @Override protected Integer createSnapshot() { - return droppedKeys.size(); + return entries.size(); } @Override @@ -116,27 +114,28 @@ class PlayerInventoryStorageImpl extends InventoryStorageImpl implements PlayerI // effectively cancel dropping the stacks int previousSize = snapshot; - while (droppedKeys.size() > previousSize) { - droppedKeys.remove(droppedKeys.size() - 1); - droppedCounts.remove(droppedCounts.size() - 1); + while (entries.size() > previousSize) { + entries.remove(entries.size() - 1); } } @Override protected void onFinalCommit() { // actually drop the stacks - for (int i = 0; i < droppedKeys.size(); ++i) { - ItemVariant key = droppedKeys.get(i); + for (Entry entry : entries) { + long remainder = entry.amount; - while (droppedCounts.get(i) > 0) { - int dropped = (int) Math.min(key.getItem().getMaxCount(), droppedCounts.get(i)); - playerInventory.player.dropStack(key.toStack(dropped)); - droppedCounts.set(i, droppedCounts.get(i) - dropped); + while (remainder > 0) { + int dropped = (int) Math.min(entry.key.getItem().getMaxCount(), remainder); + playerInventory.player.dropItem(entry.key.toStack(dropped), entry.throwRandomly, entry.retainOwnership); + remainder -= dropped; } } - droppedKeys.clear(); - droppedCounts.clear(); + entries.clear(); + } + + private record Entry(ItemVariant key, long amount, boolean throwRandomly, boolean retainOwnership) { } } }