mirror of
https://github.com/PaperMC/Paper.git
synced 2025-08-01 04:32:11 -07:00
Add Player#give (#11995)
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package io.papermc.paper.entity;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* A result type used by {@link org.bukkit.entity.Player#give(ItemStack...)} and its overloads.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface PlayerGiveResult {
|
||||
|
||||
/**
|
||||
* A collection of itemstacks that were not added to the player's inventory as they did not fit.
|
||||
* The collection is derived from the collections of items to add by creating copies of each stack that was not
|
||||
* fully added to the inventory and assigning the non-added count as their amount.
|
||||
* <p>
|
||||
* Itemstacks found here *may* also be found as item entities in the {@link #drops()} collection, as the
|
||||
* give logic may have dropped them.
|
||||
*
|
||||
* @return the unmodifiable collection of itemstacks that are leftover as they could not be added. Each element is a
|
||||
* copy of the input stack they are derived from.
|
||||
*/
|
||||
@Unmodifiable
|
||||
Collection<ItemStack> leftovers();
|
||||
|
||||
/**
|
||||
* A collection of item entities dropped as a result of this call to {@link org.bukkit.entity.Player#give(ItemStack...)}.
|
||||
* The item entities contained here are not guaranteed to match the {@link #leftovers()} as plugins may cancel the
|
||||
* spawning of item entities.
|
||||
*
|
||||
* @return the unmodifiable collection of dropped item entities.
|
||||
*/
|
||||
@Unmodifiable
|
||||
Collection<Item> drops();
|
||||
|
||||
}
|
@@ -6,10 +6,12 @@ import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import io.papermc.paper.entity.LookAnchor;
|
||||
import io.papermc.paper.entity.PlayerGiveResult;
|
||||
import org.bukkit.BanEntry;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Effect;
|
||||
@@ -3892,4 +3894,38 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
*/
|
||||
void sendEntityEffect(org.bukkit.@NotNull EntityEffect effect, @NotNull Entity target);
|
||||
// Paper end - entity effect API
|
||||
|
||||
/**
|
||||
* Gives the player the items following full vanilla logic,
|
||||
* making the player drop the items that did not fit into
|
||||
* the inventory.
|
||||
*
|
||||
* @param items the items to give.
|
||||
* @return the result of this method, holding leftovers and spawned items.
|
||||
*/
|
||||
default @NotNull PlayerGiveResult give(@NotNull final ItemStack @NotNull ... items) {
|
||||
return this.give(List.of(items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the player those items following full vanilla logic,
|
||||
* making the player drop the items that did not fit into
|
||||
* the inventory.
|
||||
*
|
||||
* @param items the items to give
|
||||
* @return the result of this method, holding leftovers and spawned items.
|
||||
*/
|
||||
default @NotNull PlayerGiveResult give(@NotNull final Collection<@NotNull ItemStack> items) {
|
||||
return this.give(items, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the player those items following full vanilla logic.
|
||||
*
|
||||
* @param items the items to give
|
||||
* @param dropIfFull whether the player should drop items that
|
||||
* did not fit the inventory
|
||||
* @return the result of this method, holding leftovers and spawned items.
|
||||
*/
|
||||
@NotNull PlayerGiveResult give(@NotNull Collection<@NotNull ItemStack> items, boolean dropIfFull);
|
||||
}
|
||||
|
@@ -0,0 +1,20 @@
|
||||
package io.papermc.paper.entity;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public record PaperPlayerGiveResult(
|
||||
@Unmodifiable Collection<ItemStack> leftovers,
|
||||
@Unmodifiable Collection<Item> drops
|
||||
) implements PlayerGiveResult {
|
||||
|
||||
public static final PlayerGiveResult EMPTY = new PaperPlayerGiveResult(
|
||||
Collections.emptyList(), Collections.emptyList()
|
||||
);
|
||||
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
package org.bukkit.craftbukkit.entity;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
@@ -8,6 +9,8 @@ import com.mojang.datafixers.util.Pair;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.papermc.paper.FeatureHooks;
|
||||
import io.papermc.paper.entity.LookAnchor;
|
||||
import io.papermc.paper.entity.PaperPlayerGiveResult;
|
||||
import io.papermc.paper.entity.PlayerGiveResult;
|
||||
import it.unimi.dsi.fastutil.shorts.ShortArraySet;
|
||||
import it.unimi.dsi.fastutil.shorts.ShortSet;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -101,6 +104,7 @@ import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeMap;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.food.FoodData;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.level.GameType;
|
||||
@@ -176,6 +180,7 @@ import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.EnderPearl;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerExpCooldownChangeEvent;
|
||||
@@ -3545,4 +3550,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(((CraftEntity) target).getHandle(), effect.getData()));
|
||||
}
|
||||
// Paper end - entity effect API
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerGiveResult give(@NotNull final Collection<@NotNull ItemStack> items, final boolean dropIfFull) {
|
||||
Preconditions.checkArgument(items != null, "items cannot be null");
|
||||
if (items.isEmpty()) return PaperPlayerGiveResult.EMPTY; // Early opt out for empty input.
|
||||
|
||||
// Validate all items before attempting to spawn any.
|
||||
for (final ItemStack item : items) {
|
||||
Preconditions.checkArgument(item != null, "ItemStack cannot be null");
|
||||
Preconditions.checkArgument(!item.isEmpty(), "ItemStack cannot be empty");
|
||||
Preconditions.checkArgument(item.getAmount() <= item.getMaxStackSize(), "ItemStack amount cannot be greater than its max stack size");
|
||||
}
|
||||
|
||||
final ServerPlayer handle = this.getHandle();
|
||||
final ImmutableList.Builder<Item> drops = ImmutableList.builder();
|
||||
final ImmutableList.Builder<ItemStack> leftovers = ImmutableList.builder();
|
||||
for (final ItemStack item : items) {
|
||||
final net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
|
||||
final boolean added = handle.getInventory().add(nmsStack);
|
||||
if (added && nmsStack.isEmpty()) continue; // Item was fully added, neither a drop nor a leftover is needed.
|
||||
|
||||
leftovers.add(CraftItemStack.asBukkitCopy(nmsStack)); // Insert copy to avoid mutation to the dropped item from affecting leftovers
|
||||
if (!dropIfFull) continue;
|
||||
|
||||
final ItemEntity entity = handle.drop(nmsStack, false, true, false);
|
||||
if (entity != null) drops.add((Item) entity.getBukkitEntity());
|
||||
}
|
||||
|
||||
handle.containerMenu.broadcastChanges();
|
||||
return new PaperPlayerGiveResult(leftovers.build(), drops.build());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user