minecraft-source/src/net/minecraft/server/commands/LootCommand.java

296 lines
22 KiB
Java

package net.minecraft.server.commands;
import net.minecraft.world.level.storage.loot.LootTables;
import net.minecraft.commands.SharedSuggestionProvider;
import java.util.concurrent.CompletableFuture;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import com.mojang.brigadier.Message;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.entity.Entity;
import net.minecraft.server.level.ServerPlayer;
import java.util.Collection;
import java.util.Objects;
import java.util.Iterator;
import com.google.common.collect.Lists;
import net.minecraft.world.item.ItemStack;
import java.util.List;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.Container;
import net.minecraft.core.BlockPos;
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import net.minecraft.commands.arguments.SlotArgument;
import com.mojang.brigadier.builder.ArgumentBuilder;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.commands.arguments.item.ItemArgument;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.arguments.ArgumentType;
import net.minecraft.commands.arguments.ResourceLocationArgument;
import net.minecraft.commands.Commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import net.minecraft.commands.CommandSourceStack;
import com.mojang.brigadier.suggestion.SuggestionProvider;
public class LootCommand {
public static final SuggestionProvider<CommandSourceStack> SUGGEST_LOOT_TABLE;
private static final DynamicCommandExceptionType ERROR_NO_HELD_ITEMS;
private static final DynamicCommandExceptionType ERROR_NO_LOOT_TABLE;
public static void register(final CommandDispatcher<CommandSourceStack> commandDispatcher) {
commandDispatcher.register((LiteralArgumentBuilder)LootCommand.<LiteralArgumentBuilder>addTargets((LiteralArgumentBuilder)Commands.literal("loot").requires(cq -> cq.hasPermission(2)), (argumentBuilder, b) -> argumentBuilder.then(Commands.literal("fish").then(Commands.argument("loot_table", (com.mojang.brigadier.arguments.ArgumentType<Object>)ResourceLocationArgument.id()).suggests((SuggestionProvider)LootCommand.SUGGEST_LOOT_TABLE).then(((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)Commands.argument("pos", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).executes(commandContext -> dropFishingLoot((CommandContext<CommandSourceStack>)commandContext, ResourceLocationArgument.getId((CommandContext<CommandSourceStack>)commandContext, "loot_table"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "pos"), ItemStack.EMPTY, b))).then(Commands.argument("tool", (com.mojang.brigadier.arguments.ArgumentType<Object>)ItemArgument.item()).executes(commandContext -> dropFishingLoot((CommandContext<CommandSourceStack>)commandContext, ResourceLocationArgument.getId((CommandContext<CommandSourceStack>)commandContext, "loot_table"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "pos"), ItemArgument.getItem((com.mojang.brigadier.context.CommandContext<Object>)commandContext, "tool").createItemStack(1, false), b)))).then(Commands.literal("mainhand").executes(commandContext -> dropFishingLoot((CommandContext<CommandSourceStack>)commandContext, ResourceLocationArgument.getId((CommandContext<CommandSourceStack>)commandContext, "loot_table"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "pos"), getSourceHandItem((CommandSourceStack)commandContext.getSource(), EquipmentSlot.MAINHAND), b)))).then(Commands.literal("offhand").executes(commandContext -> dropFishingLoot((CommandContext<CommandSourceStack>)commandContext, ResourceLocationArgument.getId((CommandContext<CommandSourceStack>)commandContext, "loot_table"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "pos"), getSourceHandItem((CommandSourceStack)commandContext.getSource(), EquipmentSlot.OFFHAND), b)))))).then(Commands.literal("loot").then(Commands.argument("loot_table", (com.mojang.brigadier.arguments.ArgumentType<Object>)ResourceLocationArgument.id()).suggests((SuggestionProvider)LootCommand.SUGGEST_LOOT_TABLE).executes(commandContext -> dropChestLoot((CommandContext<CommandSourceStack>)commandContext, ResourceLocationArgument.getId((CommandContext<CommandSourceStack>)commandContext, "loot_table"), b)))).then(Commands.literal("kill").then(Commands.argument("target", (com.mojang.brigadier.arguments.ArgumentType<Object>)EntityArgument.entity()).executes(commandContext -> dropKillLoot((CommandContext<CommandSourceStack>)commandContext, EntityArgument.getEntity((CommandContext<CommandSourceStack>)commandContext, "target"), b)))).then(Commands.literal("mine").then(((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)Commands.argument("pos", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).executes(commandContext -> dropBlockLoot((CommandContext<CommandSourceStack>)commandContext, BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "pos"), ItemStack.EMPTY, b))).then(Commands.argument("tool", (com.mojang.brigadier.arguments.ArgumentType<Object>)ItemArgument.item()).executes(commandContext -> dropBlockLoot((CommandContext<CommandSourceStack>)commandContext, BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "pos"), ItemArgument.getItem((com.mojang.brigadier.context.CommandContext<Object>)commandContext, "tool").createItemStack(1, false), b)))).then(Commands.literal("mainhand").executes(commandContext -> dropBlockLoot((CommandContext<CommandSourceStack>)commandContext, BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "pos"), getSourceHandItem((CommandSourceStack)commandContext.getSource(), EquipmentSlot.MAINHAND), b)))).then(Commands.literal("offhand").executes(commandContext -> dropBlockLoot((CommandContext<CommandSourceStack>)commandContext, BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "pos"), getSourceHandItem((CommandSourceStack)commandContext.getSource(), EquipmentSlot.OFFHAND), b)))))));
}
private static <T extends ArgumentBuilder<CommandSourceStack, T>> T addTargets(final T argumentBuilder, final TailProvider c) {
return (T)argumentBuilder.then(((LiteralArgumentBuilder)Commands.literal("replace").then(Commands.literal("entity").then(Commands.argument("entities", (com.mojang.brigadier.arguments.ArgumentType<Object>)EntityArgument.entities()).then(c.construct(Commands.argument("slot", (com.mojang.brigadier.arguments.ArgumentType<Object>)SlotArgument.slot()), (commandContext, list, a) -> entityReplace(EntityArgument.getEntities(commandContext, "entities"), SlotArgument.getSlot(commandContext, "slot"), list.size(), list, a)).then((ArgumentBuilder)c.construct(Commands.argument("count", (com.mojang.brigadier.arguments.ArgumentType<Object>)IntegerArgumentType.integer(0)), (commandContext, list, a) -> entityReplace(EntityArgument.getEntities(commandContext, "entities"), SlotArgument.getSlot(commandContext, "slot"), IntegerArgumentType.getInteger((CommandContext)commandContext, "count"), list, a))))))).then(Commands.literal("block").then(Commands.argument("targetPos", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).then(c.construct(Commands.argument("slot", (com.mojang.brigadier.arguments.ArgumentType<Object>)SlotArgument.slot()), (commandContext, list, a) -> blockReplace((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos(commandContext, "targetPos"), SlotArgument.getSlot(commandContext, "slot"), list.size(), list, a)).then((ArgumentBuilder)c.construct(Commands.argument("count", (com.mojang.brigadier.arguments.ArgumentType<Object>)IntegerArgumentType.integer(0)), (commandContext, list, a) -> blockReplace((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos(commandContext, "targetPos"), IntegerArgumentType.getInteger((CommandContext)commandContext, "slot"), IntegerArgumentType.getInteger((CommandContext)commandContext, "count"), list, a))))))).then(Commands.literal("insert").then((ArgumentBuilder)c.construct(Commands.argument("targetPos", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()), (commandContext, list, a) -> blockDistribute((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos(commandContext, "targetPos"), list, a)))).then(Commands.literal("give").then((ArgumentBuilder)c.construct(Commands.argument("players", (com.mojang.brigadier.arguments.ArgumentType<Object>)EntityArgument.players()), (commandContext, list, a) -> playerGive(EntityArgument.getPlayers(commandContext, "players"), list, a)))).then(Commands.literal("spawn").then((ArgumentBuilder)c.construct(Commands.argument("targetPos", (com.mojang.brigadier.arguments.ArgumentType<Object>)Vec3Argument.vec3()), (commandContext, list, a) -> dropInWorld((CommandSourceStack)commandContext.getSource(), Vec3Argument.getVec3(commandContext, "targetPos"), list, a))));
}
private static Container getContainer(final CommandSourceStack cq, final BlockPos fk) throws CommandSyntaxException {
final BlockEntity bwi3 = cq.getLevel().getBlockEntity(fk);
if (!(bwi3 instanceof Container)) {
throw ReplaceItemCommand.ERROR_NOT_A_CONTAINER.create();
}
return (Container)bwi3;
}
private static int blockDistribute(final CommandSourceStack cq, final BlockPos fk, final List<ItemStack> list, final Callback a) throws CommandSyntaxException {
final Container ajb5 = getContainer(cq, fk);
final List<ItemStack> list2 = Lists.newArrayListWithCapacity(list.size());
for (final ItemStack bek8 : list) {
if (distributeToContainer(ajb5, bek8.copy())) {
ajb5.setChanged();
list2.add(bek8);
}
}
a.accept(list2);
return list2.size();
}
private static boolean distributeToContainer(final Container ajb, final ItemStack bek) {
boolean boolean3 = false;
for (int integer4 = 0; integer4 < ajb.getContainerSize() && !bek.isEmpty(); ++integer4) {
final ItemStack bek2 = ajb.getItem(integer4);
if (ajb.canPlaceItem(integer4, bek)) {
if (bek2.isEmpty()) {
ajb.setItem(integer4, bek);
boolean3 = true;
break;
}
if (canMergeItems(bek2, bek)) {
final int integer5 = bek.getMaxStackSize() - bek2.getCount();
final int integer6 = Math.min(bek.getCount(), integer5);
bek.shrink(integer6);
bek2.grow(integer6);
boolean3 = true;
}
}
}
return boolean3;
}
private static int blockReplace(final CommandSourceStack cq, final BlockPos fk, final int integer3, final int integer4, final List<ItemStack> list, final Callback a) throws CommandSyntaxException {
final Container ajb7 = getContainer(cq, fk);
final int integer5 = ajb7.getContainerSize();
if (integer3 < 0 || integer3 >= integer5) {
throw ReplaceItemCommand.ERROR_INAPPLICABLE_SLOT.create(integer3);
}
final List<ItemStack> list2 = Lists.newArrayListWithCapacity(list.size());
for (int integer6 = 0; integer6 < integer4; ++integer6) {
final int integer7 = integer3 + integer6;
final ItemStack bek12 = (integer6 < list.size()) ? list.get(integer6) : ItemStack.EMPTY;
if (ajb7.canPlaceItem(integer7, bek12)) {
ajb7.setItem(integer7, bek12);
list2.add(bek12);
}
}
a.accept(list2);
return list2.size();
}
private static boolean canMergeItems(final ItemStack bek1, final ItemStack bek2) {
return bek1.getItem() == bek2.getItem() && bek1.getDamageValue() == bek2.getDamageValue() && bek1.getCount() <= bek1.getMaxStackSize() && Objects.equals(bek1.getTag(), bek2.getTag());
}
private static int playerGive(final Collection<ServerPlayer> collection, final List<ItemStack> list, final Callback a) throws CommandSyntaxException {
final List<ItemStack> list2 = Lists.newArrayListWithCapacity(list.size());
for (final ItemStack bek6 : list) {
for (final ServerPlayer xe8 : collection) {
if (xe8.inventory.add(bek6.copy())) {
list2.add(bek6);
}
}
}
a.accept(list2);
return list2.size();
}
private static void setSlots(final Entity akn, final List<ItemStack> list2, final int integer3, final int integer4, final List<ItemStack> list5) {
for (int integer5 = 0; integer5 < integer4; ++integer5) {
final ItemStack bek7 = (integer5 < list2.size()) ? list2.get(integer5) : ItemStack.EMPTY;
if (akn.setSlot(integer3 + integer5, bek7.copy())) {
list5.add(bek7);
}
}
}
private static int entityReplace(final Collection<? extends Entity> collection, final int integer2, final int integer3, final List<ItemStack> list, final Callback a) throws CommandSyntaxException {
final List<ItemStack> list2 = Lists.newArrayListWithCapacity(list.size());
for (final Entity akn8 : collection) {
if (akn8 instanceof ServerPlayer) {
final ServerPlayer xe9 = (ServerPlayer)akn8;
xe9.inventoryMenu.broadcastChanges();
setSlots(akn8, list, integer2, integer3, list2);
xe9.inventoryMenu.broadcastChanges();
}
else {
setSlots(akn8, list, integer2, integer3, list2);
}
}
a.accept(list2);
return list2.size();
}
private static int dropInWorld(final CommandSourceStack cq, final Vec3 cvi, final List<ItemStack> list, final Callback a) throws CommandSyntaxException {
final ServerLevel xd5 = cq.getLevel();
final ServerLevel bjt;
final ItemEntity avy4;
list.forEach(bek -> {
avy4 = new ItemEntity(bjt, cvi.x, cvi.y, cvi.z, bek.copy());
avy4.setDefaultPickUpDelay();
bjt.addFreshEntity(avy4);
return;
});
a.accept(list);
return list.size();
}
private static void callback(final CommandSourceStack cq, final List<ItemStack> list) {
if (list.size() == 1) {
final ItemStack bek3 = list.get(0);
cq.sendSuccess(new TranslatableComponent("commands.drop.success.single", new Object[] { bek3.getCount(), bek3.getDisplayName() }), false);
}
else {
cq.sendSuccess(new TranslatableComponent("commands.drop.success.multiple", new Object[] { list.size() }), false);
}
}
private static void callback(final CommandSourceStack cq, final List<ItemStack> list, final ResourceLocation sm) {
if (list.size() == 1) {
final ItemStack bek4 = list.get(0);
cq.sendSuccess(new TranslatableComponent("commands.drop.success.single_with_table", new Object[] { bek4.getCount(), bek4.getDisplayName(), sm }), false);
}
else {
cq.sendSuccess(new TranslatableComponent("commands.drop.success.multiple_with_table", new Object[] { list.size(), sm }), false);
}
}
private static ItemStack getSourceHandItem(final CommandSourceStack cq, final EquipmentSlot aks) throws CommandSyntaxException {
final Entity akn3 = cq.getEntityOrException();
if (akn3 instanceof LivingEntity) {
return ((LivingEntity)akn3).getItemBySlot(aks);
}
throw LootCommand.ERROR_NO_HELD_ITEMS.create(akn3.getDisplayName());
}
private static int dropBlockLoot(final CommandContext<CommandSourceStack> commandContext, final BlockPos fk, final ItemStack bek, final DropConsumer b) throws CommandSyntaxException {
final CommandSourceStack cq5 = (CommandSourceStack)commandContext.getSource();
final ServerLevel xd6 = cq5.getLevel();
final BlockState byg7 = xd6.getBlockState(fk);
final BlockEntity bwi8 = xd6.getBlockEntity(fk);
final LootContext.Builder a9 = new LootContext.Builder(xd6).<BlockPos>withParameter(LootContextParams.BLOCK_POS, fk).<BlockState>withParameter(LootContextParams.BLOCK_STATE, byg7).<BlockEntity>withOptionalParameter(LootContextParams.BLOCK_ENTITY, bwi8).<Entity>withOptionalParameter(LootContextParams.THIS_ENTITY, cq5.getEntity()).<ItemStack>withParameter(LootContextParams.TOOL, bek);
final List<ItemStack> list2 = byg7.getDrops(a9);
return b.accept(commandContext, list2, list -> callback(cq5, list, byg7.getBlock().getLootTable()));
}
private static int dropKillLoot(final CommandContext<CommandSourceStack> commandContext, final Entity akn, final DropConsumer b) throws CommandSyntaxException {
if (!(akn instanceof LivingEntity)) {
throw LootCommand.ERROR_NO_LOOT_TABLE.create(akn.getDisplayName());
}
final ResourceLocation sm4 = ((LivingEntity)akn).getLootTable();
final CommandSourceStack cq5 = (CommandSourceStack)commandContext.getSource();
final LootContext.Builder a6 = new LootContext.Builder(cq5.getLevel());
final Entity akn2 = cq5.getEntity();
if (akn2 instanceof Player) {
a6.<Player>withParameter(LootContextParams.LAST_DAMAGE_PLAYER, (Player)akn2);
}
a6.<DamageSource>withParameter(LootContextParams.DAMAGE_SOURCE, DamageSource.MAGIC);
a6.<Entity>withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, akn2);
a6.<Entity>withOptionalParameter(LootContextParams.KILLER_ENTITY, akn2);
a6.<Entity>withParameter(LootContextParams.THIS_ENTITY, akn);
a6.<BlockPos>withParameter(LootContextParams.BLOCK_POS, new BlockPos(cq5.getPosition()));
final LootTable crx8 = cq5.getServer().getLootTables().get(sm4);
final List<ItemStack> list2 = crx8.getRandomItems(a6.create(LootContextParamSets.ENTITY));
return b.accept(commandContext, list2, list -> callback(cq5, list, sm4));
}
private static int dropChestLoot(final CommandContext<CommandSourceStack> commandContext, final ResourceLocation sm, final DropConsumer b) throws CommandSyntaxException {
final CommandSourceStack cq4 = (CommandSourceStack)commandContext.getSource();
final LootContext.Builder a5 = new LootContext.Builder(cq4.getLevel()).<Entity>withOptionalParameter(LootContextParams.THIS_ENTITY, cq4.getEntity()).<BlockPos>withParameter(LootContextParams.BLOCK_POS, new BlockPos(cq4.getPosition()));
return drop(commandContext, sm, a5.create(LootContextParamSets.CHEST), b);
}
private static int dropFishingLoot(final CommandContext<CommandSourceStack> commandContext, final ResourceLocation sm, final BlockPos fk, final ItemStack bek, final DropConsumer b) throws CommandSyntaxException {
final CommandSourceStack cq6 = (CommandSourceStack)commandContext.getSource();
final LootContext cru7 = new LootContext.Builder(cq6.getLevel()).<BlockPos>withParameter(LootContextParams.BLOCK_POS, fk).<ItemStack>withParameter(LootContextParams.TOOL, bek).create(LootContextParamSets.FISHING);
return drop(commandContext, sm, cru7, b);
}
private static int drop(final CommandContext<CommandSourceStack> commandContext, final ResourceLocation sm, final LootContext cru, final DropConsumer b) throws CommandSyntaxException {
final CommandSourceStack cq5 = (CommandSourceStack)commandContext.getSource();
final LootTable crx6 = cq5.getServer().getLootTables().get(sm);
final List<ItemStack> list2 = crx6.getRandomItems(cru);
return b.accept(commandContext, list2, list -> callback(cq5, list));
}
static {
SUGGEST_LOOT_TABLE = ((commandContext, suggestionsBuilder) -> {
final LootTables cry3 = ((CommandSourceStack)commandContext.getSource()).getServer().getLootTables();
return SharedSuggestionProvider.suggestResource(cry3.getIds(), suggestionsBuilder);
});
final TranslatableComponent translatableComponent;
ERROR_NO_HELD_ITEMS = new DynamicCommandExceptionType(object -> {
new TranslatableComponent("commands.drop.no_held_items", new Object[] { object });
return translatableComponent;
});
final TranslatableComponent translatableComponent2;
ERROR_NO_LOOT_TABLE = new DynamicCommandExceptionType(object -> {
new TranslatableComponent("commands.drop.no_loot_table", new Object[] { object });
return translatableComponent2;
});
}
@FunctionalInterface
interface TailProvider {
ArgumentBuilder<CommandSourceStack, ?> construct(final ArgumentBuilder<CommandSourceStack, ?> argumentBuilder, final DropConsumer b);
}
@FunctionalInterface
interface DropConsumer {
int accept(final CommandContext<CommandSourceStack> commandContext, final List<ItemStack> list, final Callback a) throws CommandSyntaxException;
}
@FunctionalInterface
interface Callback {
void accept(final List<ItemStack> list) throws CommandSyntaxException;
}
}