LootCommand.java

net.minecraft.server.commands.LootCommand

信息

  • 全限定名:net.minecraft.server.commands.LootCommand
  • 类型:public class
  • 包:net.minecraft.server.commands
  • 源码路径:src/main/java/net/minecraft/server/commands/LootCommand.java
  • 起始行号:L45
  • 职责:

    TODO

字段/常量

  • ERROR_NO_HELD_ITEMS

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L46
    • 说明:

      TODO

  • ERROR_NO_ENTITY_LOOT_TABLE

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L49
    • 说明:

      TODO

  • ERROR_NO_BLOCK_LOOT_TABLE

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L52
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.server.commands.LootCommand.Callback

    • 类型: interface
    • 修饰符: private
    • 源码定位: L493
    • 说明:

      TODO

  • net.minecraft.server.commands.LootCommand.DropConsumer

    • 类型: interface
    • 修饰符: private
    • 源码定位: L498
    • 说明:

      TODO

  • net.minecraft.server.commands.LootCommand.TailProvider

    • 类型: interface
    • 修饰符: private
    • 源码定位: L503
    • 说明:

      TODO

构造器

方法

下面的方法块按源码顺序生成。

public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) @ L56

  • 方法名:register
  • 源码定位:L56
  • 返回类型:void
  • 修饰符:public static

参数:

  • dispatcher: CommandDispatcher
  • context: CommandBuildContext

说明:

TODO

private static <T extends ArgumentBuilder<CommandSourceStack,T>> T addTargets(T root, LootCommand.TailProvider tail) @ L169

  • 方法名:addTargets
  • 源码定位:L169
  • 返回类型:<T extends ArgumentBuilder<CommandSourceStack,T>> T
  • 修饰符:private static

参数:

  • root: T
  • tail: LootCommand.TailProvider

说明:

TODO

private static Container getContainer(CommandSourceStack source, BlockPos pos) @ L260

  • 方法名:getContainer
  • 源码定位:L260
  • 返回类型:Container
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • pos: BlockPos

说明:

TODO

private static int blockDistribute(CommandSourceStack source, BlockPos pos, List<ItemStack> drops, LootCommand.Callback callback) @ L269

  • 方法名:blockDistribute
  • 源码定位:L269
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • pos: BlockPos
  • drops: List
  • callback: LootCommand.Callback

说明:

TODO

private static boolean distributeToContainer(Container container, ItemStack itemStack) @ L284

  • 方法名:distributeToContainer
  • 源码定位:L284
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • container: Container
  • itemStack: ItemStack

说明:

TODO

private static int blockReplace(CommandSourceStack source, BlockPos pos, int startSlot, int slotCount, List<ItemStack> drops, LootCommand.Callback callback) @ L309

  • 方法名:blockReplace
  • 源码定位:L309
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • pos: BlockPos
  • startSlot: int
  • slotCount: int
  • drops: List
  • callback: LootCommand.Callback

说明:

TODO

private static boolean canMergeItems(ItemStack a, ItemStack b) @ L331

  • 方法名:canMergeItems
  • 源码定位:L331
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • a: ItemStack
  • b: ItemStack

说明:

TODO

private static int playerGive(Collection<ServerPlayer> players, List<ItemStack> drops, LootCommand.Callback callback) @ L335

  • 方法名:playerGive
  • 源码定位:L335
  • 返回类型:int
  • 修饰符:private static

参数:

  • players: Collection
  • drops: List
  • callback: LootCommand.Callback

说明:

TODO

private static void setSlots(Entity entity, List<ItemStack> itemsToSet, int startSlot, int count, List<ItemStack> usedItems) @ L350

  • 方法名:setSlots
  • 源码定位:L350
  • 返回类型:void
  • 修饰符:private static

参数:

  • entity: Entity
  • itemsToSet: List
  • startSlot: int
  • count: int
  • usedItems: List

说明:

TODO

private static int entityReplace(Collection<?extends Entity> entities, int startSlot, int count, List<ItemStack> drops, LootCommand.Callback callback) @ L360

  • 方法名:entityReplace
  • 源码定位:L360
  • 返回类型:int
  • 修饰符:private static

参数:

  • entities: Collection<?extends Entity>
  • startSlot: int
  • count: int
  • drops: List
  • callback: LootCommand.Callback

说明:

TODO

private static int dropInWorld(CommandSourceStack source, Vec3 pos, List<ItemStack> drops, LootCommand.Callback callback) @ L376

  • 方法名:dropInWorld
  • 源码定位:L376
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • pos: Vec3
  • drops: List
  • callback: LootCommand.Callback

说明:

TODO

private static void callback(CommandSourceStack source, List<ItemStack> drops) @ L387

  • 方法名:callback
  • 源码定位:L387
  • 返回类型:void
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • drops: List

说明:

TODO

private static void callback(CommandSourceStack source, List<ItemStack> drops, ResourceKey<LootTable> location) @ L396

  • 方法名:callback
  • 源码定位:L396
  • 返回类型:void
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • drops: List
  • location: ResourceKey

说明:

TODO

private static ItemStack getSourceHandItem(CommandSourceStack source, EquipmentSlot slot) @ L412

  • 方法名:getSourceHandItem
  • 源码定位:L412
  • 返回类型:ItemStack
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • slot: EquipmentSlot

说明:

TODO

private static int dropBlockLoot(CommandContext<CommandSourceStack> context, BlockPos pos, ItemInstance tool, LootCommand.DropConsumer output) @ L421

  • 方法名:dropBlockLoot
  • 源码定位:L421
  • 返回类型:int
  • 修饰符:private static

参数:

  • context: CommandContext
  • pos: BlockPos
  • tool: ItemInstance
  • output: LootCommand.DropConsumer

说明:

TODO

private static int dropKillLoot(CommandContext<CommandSourceStack> context, Entity target, LootCommand.DropConsumer output) @ L441

  • 方法名:dropKillLoot
  • 源码定位:L441
  • 返回类型:int
  • 修饰符:private static

参数:

  • context: CommandContext
  • target: Entity
  • output: LootCommand.DropConsumer

说明:

TODO

private static int dropChestLoot(CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, LootCommand.DropConsumer output) @ L465

  • 方法名:dropChestLoot
  • 源码定位:L465
  • 返回类型:int
  • 修饰符:private static

参数:

  • context: CommandContext
  • lootTable: Holder
  • output: LootCommand.DropConsumer

说明:

TODO

private static int dropFishingLoot(CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, BlockPos pos, ItemInstance tool, LootCommand.DropConsumer output) @ L474

  • 方法名:dropFishingLoot
  • 源码定位:L474
  • 返回类型:int
  • 修饰符:private static

参数:

  • context: CommandContext
  • lootTable: Holder
  • pos: BlockPos
  • tool: ItemInstance
  • output: LootCommand.DropConsumer

说明:

TODO

private static int drop(CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, LootParams lootParams, LootCommand.DropConsumer output) @ L486

  • 方法名:drop
  • 源码定位:L486
  • 返回类型:int
  • 修饰符:private static

参数:

  • context: CommandContext
  • lootTable: Holder
  • lootParams: LootParams
  • output: LootCommand.DropConsumer

说明:

TODO

代码

public class LootCommand {
    private static final DynamicCommandExceptionType ERROR_NO_HELD_ITEMS = new DynamicCommandExceptionType(
        entity -> Component.translatableEscape("commands.drop.no_held_items", entity)
    );
    private static final DynamicCommandExceptionType ERROR_NO_ENTITY_LOOT_TABLE = new DynamicCommandExceptionType(
        entity -> Component.translatableEscape("commands.drop.no_loot_table.entity", entity)
    );
    private static final DynamicCommandExceptionType ERROR_NO_BLOCK_LOOT_TABLE = new DynamicCommandExceptionType(
        block -> Component.translatableEscape("commands.drop.no_loot_table.block", block)
    );
 
    public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) {
        dispatcher.register(
            addTargets(
                Commands.literal("loot").requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS)),
                (target, output) -> target.then(
                        Commands.literal("fish")
                            .then(
                                Commands.argument("loot_table", ResourceOrIdArgument.lootTable(context))
                                    .then(
                                        Commands.argument("pos", BlockPosArgument.blockPos())
                                            .executes(
                                                c -> dropFishingLoot(
                                                    c,
                                                    ResourceOrIdArgument.getLootTable(c, "loot_table"),
                                                    BlockPosArgument.getLoadedBlockPos(c, "pos"),
                                                    ItemStack.EMPTY,
                                                    output
                                                )
                                            )
                                            .then(
                                                Commands.argument("tool", ItemArgument.item(context))
                                                    .executes(
                                                        c -> dropFishingLoot(
                                                            c,
                                                            ResourceOrIdArgument.getLootTable(c, "loot_table"),
                                                            BlockPosArgument.getLoadedBlockPos(c, "pos"),
                                                            ItemArgument.getItem(c, "tool").createItemStack(1),
                                                            output
                                                        )
                                                    )
                                            )
                                            .then(
                                                Commands.literal("mainhand")
                                                    .executes(
                                                        c -> dropFishingLoot(
                                                            c,
                                                            ResourceOrIdArgument.getLootTable(c, "loot_table"),
                                                            BlockPosArgument.getLoadedBlockPos(c, "pos"),
                                                            getSourceHandItem(c.getSource(), EquipmentSlot.MAINHAND),
                                                            output
                                                        )
                                                    )
                                            )
                                            .then(
                                                Commands.literal("offhand")
                                                    .executes(
                                                        c -> dropFishingLoot(
                                                            c,
                                                            ResourceOrIdArgument.getLootTable(c, "loot_table"),
                                                            BlockPosArgument.getLoadedBlockPos(c, "pos"),
                                                            getSourceHandItem(c.getSource(), EquipmentSlot.OFFHAND),
                                                            output
                                                        )
                                                    )
                                            )
                                    )
                            )
                    )
                    .then(
                        Commands.literal("loot")
                            .then(
                                Commands.argument("loot_table", ResourceOrIdArgument.lootTable(context))
                                    .executes(c -> dropChestLoot(c, ResourceOrIdArgument.getLootTable(c, "loot_table"), output))
                            )
                    )
                    .then(
                        Commands.literal("kill")
                            .then(
                                Commands.argument("target", EntityArgument.entity())
                                    .executes(c -> dropKillLoot(c, EntityArgument.getEntity(c, "target"), output))
                            )
                    )
                    .then(
                        Commands.literal("mine")
                            .then(
                                Commands.argument("pos", BlockPosArgument.blockPos())
                                    .executes(c -> dropBlockLoot(c, BlockPosArgument.getLoadedBlockPos(c, "pos"), ItemStack.EMPTY, output))
                                    .then(
                                        Commands.argument("tool", ItemArgument.item(context))
                                            .executes(
                                                c -> dropBlockLoot(
                                                    c, BlockPosArgument.getLoadedBlockPos(c, "pos"), ItemArgument.getItem(c, "tool").createItemStack(1), output
                                                )
                                            )
                                    )
                                    .then(
                                        Commands.literal("mainhand")
                                            .executes(
                                                c -> dropBlockLoot(
                                                    c,
                                                    BlockPosArgument.getLoadedBlockPos(c, "pos"),
                                                    getSourceHandItem(c.getSource(), EquipmentSlot.MAINHAND),
                                                    output
                                                )
                                            )
                                    )
                                    .then(
                                        Commands.literal("offhand")
                                            .executes(
                                                c -> dropBlockLoot(
                                                    c,
                                                    BlockPosArgument.getLoadedBlockPos(c, "pos"),
                                                    getSourceHandItem(c.getSource(), EquipmentSlot.OFFHAND),
                                                    output
                                                )
                                            )
                                    )
                            )
                    )
            )
        );
    }
 
    private static <T extends ArgumentBuilder<CommandSourceStack, T>> T addTargets(T root, LootCommand.TailProvider tail) {
        return root.then(
                Commands.literal("replace")
                    .then(
                        Commands.literal("entity")
                            .then(
                                Commands.argument("entities", EntityArgument.entities())
                                    .then(
                                        tail.construct(
                                                Commands.argument("slot", SlotArgument.slot()),
                                                (c, drops, callback) -> entityReplace(
                                                    EntityArgument.getEntities(c, "entities"), SlotArgument.getSlot(c, "slot"), drops.size(), drops, callback
                                                )
                                            )
                                            .then(
                                                tail.construct(
                                                    Commands.argument("count", IntegerArgumentType.integer(0)),
                                                    (c, drops, callback) -> entityReplace(
                                                        EntityArgument.getEntities(c, "entities"),
                                                        SlotArgument.getSlot(c, "slot"),
                                                        IntegerArgumentType.getInteger(c, "count"),
                                                        drops,
                                                        callback
                                                    )
                                                )
                                            )
                                    )
                            )
                    )
                    .then(
                        Commands.literal("block")
                            .then(
                                Commands.argument("targetPos", BlockPosArgument.blockPos())
                                    .then(
                                        tail.construct(
                                                Commands.argument("slot", SlotArgument.slot()),
                                                (c, drops, callback) -> blockReplace(
                                                    c.getSource(),
                                                    BlockPosArgument.getLoadedBlockPos(c, "targetPos"),
                                                    SlotArgument.getSlot(c, "slot"),
                                                    drops.size(),
                                                    drops,
                                                    callback
                                                )
                                            )
                                            .then(
                                                tail.construct(
                                                    Commands.argument("count", IntegerArgumentType.integer(0)),
                                                    (c, drops, callback) -> blockReplace(
                                                        c.getSource(),
                                                        BlockPosArgument.getLoadedBlockPos(c, "targetPos"),
                                                        IntegerArgumentType.getInteger(c, "slot"),
                                                        IntegerArgumentType.getInteger(c, "count"),
                                                        drops,
                                                        callback
                                                    )
                                                )
                                            )
                                    )
                            )
                    )
            )
            .then(
                Commands.literal("insert")
                    .then(
                        tail.construct(
                            Commands.argument("targetPos", BlockPosArgument.blockPos()),
                            (c, drops, callback) -> blockDistribute(c.getSource(), BlockPosArgument.getLoadedBlockPos(c, "targetPos"), drops, callback)
                        )
                    )
            )
            .then(
                Commands.literal("give")
                    .then(
                        tail.construct(
                            Commands.argument("players", EntityArgument.players()),
                            (c, drops, callback) -> playerGive(EntityArgument.getPlayers(c, "players"), drops, callback)
                        )
                    )
            )
            .then(
                Commands.literal("spawn")
                    .then(
                        tail.construct(
                            Commands.argument("targetPos", Vec3Argument.vec3()),
                            (c, drops, callback) -> dropInWorld(c.getSource(), Vec3Argument.getVec3(c, "targetPos"), drops, callback)
                        )
                    )
            );
    }
 
    private static Container getContainer(CommandSourceStack source, BlockPos pos) throws CommandSyntaxException {
        BlockEntity blockEntity = source.getLevel().getBlockEntity(pos);
        if (!(blockEntity instanceof Container)) {
            throw ItemCommands.ERROR_TARGET_NOT_A_CONTAINER.create(pos.getX(), pos.getY(), pos.getZ());
        } else {
            return (Container)blockEntity;
        }
    }
 
    private static int blockDistribute(CommandSourceStack source, BlockPos pos, List<ItemStack> drops, LootCommand.Callback callback) throws CommandSyntaxException {
        Container container = getContainer(source, pos);
        List<ItemStack> usedItems = Lists.newArrayListWithCapacity(drops.size());
 
        for (ItemStack drop : drops) {
            if (distributeToContainer(container, drop.copy())) {
                container.setChanged();
                usedItems.add(drop);
            }
        }
 
        callback.accept(usedItems);
        return usedItems.size();
    }
 
    private static boolean distributeToContainer(Container container, ItemStack itemStack) {
        boolean changed = false;
 
        for (int slot = 0; slot < container.getContainerSize() && !itemStack.isEmpty(); slot++) {
            ItemStack current = container.getItem(slot);
            if (container.canPlaceItem(slot, itemStack)) {
                if (current.isEmpty()) {
                    container.setItem(slot, itemStack);
                    changed = true;
                    break;
                }
 
                if (canMergeItems(current, itemStack)) {
                    int space = itemStack.getMaxStackSize() - current.getCount();
                    int count = Math.min(itemStack.getCount(), space);
                    itemStack.shrink(count);
                    current.grow(count);
                    changed = true;
                }
            }
        }
 
        return changed;
    }
 
    private static int blockReplace(CommandSourceStack source, BlockPos pos, int startSlot, int slotCount, List<ItemStack> drops, LootCommand.Callback callback) throws CommandSyntaxException {
        Container container = getContainer(source, pos);
        int maxSlot = container.getContainerSize();
        if (startSlot >= 0 && startSlot < maxSlot) {
            List<ItemStack> usedItems = Lists.newArrayListWithCapacity(drops.size());
 
            for (int i = 0; i < slotCount; i++) {
                int slot = startSlot + i;
                ItemStack toAdd = i < drops.size() ? drops.get(i) : ItemStack.EMPTY;
                if (container.canPlaceItem(slot, toAdd)) {
                    container.setItem(slot, toAdd);
                    usedItems.add(toAdd);
                }
            }
 
            callback.accept(usedItems);
            return usedItems.size();
        } else {
            throw ItemCommands.ERROR_TARGET_INAPPLICABLE_SLOT.create(startSlot);
        }
    }
 
    private static boolean canMergeItems(ItemStack a, ItemStack b) {
        return a.getCount() <= a.getMaxStackSize() && ItemStack.isSameItemSameComponents(a, b);
    }
 
    private static int playerGive(Collection<ServerPlayer> players, List<ItemStack> drops, LootCommand.Callback callback) throws CommandSyntaxException {
        List<ItemStack> usedItems = Lists.newArrayListWithCapacity(drops.size());
 
        for (ItemStack drop : drops) {
            for (ServerPlayer player : players) {
                if (player.getInventory().add(drop.copy())) {
                    usedItems.add(drop);
                }
            }
        }
 
        callback.accept(usedItems);
        return usedItems.size();
    }
 
    private static void setSlots(Entity entity, List<ItemStack> itemsToSet, int startSlot, int count, List<ItemStack> usedItems) {
        for (int i = 0; i < count; i++) {
            ItemStack item = i < itemsToSet.size() ? itemsToSet.get(i) : ItemStack.EMPTY;
            SlotAccess slotAccess = entity.getSlot(startSlot + i);
            if (slotAccess != null && slotAccess.set(item.copy())) {
                usedItems.add(item);
            }
        }
    }
 
    private static int entityReplace(Collection<? extends Entity> entities, int startSlot, int count, List<ItemStack> drops, LootCommand.Callback callback) throws CommandSyntaxException {
        List<ItemStack> usedItems = Lists.newArrayListWithCapacity(drops.size());
 
        for (Entity entity : entities) {
            if (entity instanceof ServerPlayer player) {
                setSlots(entity, drops, startSlot, count, usedItems);
                player.containerMenu.broadcastChanges();
            } else {
                setSlots(entity, drops, startSlot, count, usedItems);
            }
        }
 
        callback.accept(usedItems);
        return usedItems.size();
    }
 
    private static int dropInWorld(CommandSourceStack source, Vec3 pos, List<ItemStack> drops, LootCommand.Callback callback) throws CommandSyntaxException {
        ServerLevel level = source.getLevel();
        drops.forEach(drop -> {
            ItemEntity entity = new ItemEntity(level, pos.x, pos.y, pos.z, drop.copy());
            entity.setDefaultPickUpDelay();
            level.addFreshEntity(entity);
        });
        callback.accept(drops);
        return drops.size();
    }
 
    private static void callback(CommandSourceStack source, List<ItemStack> drops) {
        if (drops.size() == 1) {
            ItemStack drop = drops.get(0);
            source.sendSuccess(() -> Component.translatable("commands.drop.success.single", drop.getCount(), drop.getDisplayName()), false);
        } else {
            source.sendSuccess(() -> Component.translatable("commands.drop.success.multiple", drops.size()), false);
        }
    }
 
    private static void callback(CommandSourceStack source, List<ItemStack> drops, ResourceKey<LootTable> location) {
        if (drops.size() == 1) {
            ItemStack drop = drops.get(0);
            source.sendSuccess(
                () -> Component.translatable(
                    "commands.drop.success.single_with_table", drop.getCount(), drop.getDisplayName(), Component.translationArg(location.identifier())
                ),
                false
            );
        } else {
            source.sendSuccess(
                () -> Component.translatable("commands.drop.success.multiple_with_table", drops.size(), Component.translationArg(location.identifier())), false
            );
        }
    }
 
    private static ItemStack getSourceHandItem(CommandSourceStack source, EquipmentSlot slot) throws CommandSyntaxException {
        Entity entity = source.getEntityOrException();
        if (entity instanceof LivingEntity) {
            return ((LivingEntity)entity).getItemBySlot(slot);
        } else {
            throw ERROR_NO_HELD_ITEMS.create(entity.getDisplayName());
        }
    }
 
    private static int dropBlockLoot(CommandContext<CommandSourceStack> context, BlockPos pos, ItemInstance tool, LootCommand.DropConsumer output) throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerLevel level = source.getLevel();
        BlockState blockState = level.getBlockState(pos);
        BlockEntity blockEntity = level.getBlockEntity(pos);
        Optional<ResourceKey<LootTable>> lootTable = blockState.getBlock().getLootTable();
        if (lootTable.isEmpty()) {
            throw ERROR_NO_BLOCK_LOOT_TABLE.create(blockState.getBlock().getName());
        } else {
            LootParams.Builder lootParams = new LootParams.Builder(level)
                .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos))
                .withParameter(LootContextParams.BLOCK_STATE, blockState)
                .withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity)
                .withOptionalParameter(LootContextParams.THIS_ENTITY, source.getEntity())
                .withParameter(LootContextParams.TOOL, tool);
            List<ItemStack> drops = blockState.getDrops(lootParams);
            return output.accept(context, drops, usedItems -> callback(source, usedItems, lootTable.get()));
        }
    }
 
    private static int dropKillLoot(CommandContext<CommandSourceStack> context, Entity target, LootCommand.DropConsumer output) throws CommandSyntaxException {
        Optional<ResourceKey<LootTable>> lootTableId = target.getLootTable();
        if (lootTableId.isEmpty()) {
            throw ERROR_NO_ENTITY_LOOT_TABLE.create(target.getDisplayName());
        } else {
            CommandSourceStack source = context.getSource();
            LootParams.Builder builder = new LootParams.Builder(source.getLevel());
            Entity killer = source.getEntity();
            if (killer instanceof Player player) {
                builder.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, player);
            }
 
            builder.withParameter(LootContextParams.DAMAGE_SOURCE, target.damageSources().magic());
            builder.withOptionalParameter(LootContextParams.DIRECT_ATTACKING_ENTITY, killer);
            builder.withOptionalParameter(LootContextParams.ATTACKING_ENTITY, killer);
            builder.withParameter(LootContextParams.THIS_ENTITY, target);
            builder.withParameter(LootContextParams.ORIGIN, source.getPosition());
            LootParams lootParams = builder.create(LootContextParamSets.ENTITY);
            LootTable lootTable = source.getServer().reloadableRegistries().getLootTable(lootTableId.get());
            List<ItemStack> drops = lootTable.getRandomItems(lootParams);
            return output.accept(context, drops, usedItems -> callback(source, usedItems, lootTableId.get()));
        }
    }
 
    private static int dropChestLoot(CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, LootCommand.DropConsumer output) throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        LootParams lootParams = new LootParams.Builder(source.getLevel())
            .withOptionalParameter(LootContextParams.THIS_ENTITY, source.getEntity())
            .withParameter(LootContextParams.ORIGIN, source.getPosition())
            .create(LootContextParamSets.CHEST);
        return drop(context, lootTable, lootParams, output);
    }
 
    private static int dropFishingLoot(
        CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, BlockPos pos, ItemInstance tool, LootCommand.DropConsumer output
    ) throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        LootParams lootParams = new LootParams.Builder(source.getLevel())
            .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos))
            .withParameter(LootContextParams.TOOL, tool)
            .withOptionalParameter(LootContextParams.THIS_ENTITY, source.getEntity())
            .create(LootContextParamSets.FISHING);
        return drop(context, lootTable, lootParams, output);
    }
 
    private static int drop(CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, LootParams lootParams, LootCommand.DropConsumer output) throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        List<ItemStack> drops = lootTable.value().getRandomItems(lootParams);
        return output.accept(context, drops, usedItems -> callback(source, usedItems));
    }
 
    @FunctionalInterface
    private interface Callback {
        void accept(List<ItemStack> setItems) throws CommandSyntaxException;
    }
 
    @FunctionalInterface
    private interface DropConsumer {
        int accept(CommandContext<CommandSourceStack> context, List<ItemStack> drops, LootCommand.Callback successCallback) throws CommandSyntaxException;
    }
 
    @FunctionalInterface
    private interface TailProvider {
        ArgumentBuilder<CommandSourceStack, ?> construct(final ArgumentBuilder<CommandSourceStack, ?> root, LootCommand.DropConsumer consumer);
    }
}

引用的其他类

  • CommandBuildContext

    • 引用位置: 参数
  • CommandSourceStack

    • 引用位置: 参数/返回值
  • Commands

    • 引用位置: 方法调用
    • 关联成员: Commands.argument(), Commands.hasPermission(), Commands.literal()
  • EntityArgument

    • 引用位置: 方法调用
    • 关联成员: EntityArgument.entities(), EntityArgument.entity(), EntityArgument.getEntities(), EntityArgument.getEntity(), EntityArgument.getPlayers(), EntityArgument.players()
  • ResourceOrIdArgument

    • 引用位置: 方法调用
    • 关联成员: ResourceOrIdArgument.getLootTable(), ResourceOrIdArgument.lootTable()
  • SlotArgument

    • 引用位置: 方法调用
    • 关联成员: SlotArgument.getSlot(), SlotArgument.slot()
  • BlockPosArgument

    • 引用位置: 方法调用
    • 关联成员: BlockPosArgument.blockPos(), BlockPosArgument.getLoadedBlockPos()
  • Vec3Argument

    • 引用位置: 方法调用
    • 关联成员: Vec3Argument.getVec3(), Vec3Argument.vec3()
  • ItemArgument

    • 引用位置: 方法调用
    • 关联成员: ItemArgument.getItem(), ItemArgument.item()
  • BlockPos

    • 引用位置: 参数
  • Holder

    • 引用位置: 参数
  • Component

    • 引用位置: 方法调用
    • 关联成员: Component.translatable(), Component.translatableEscape(), Component.translationArg()
  • ResourceKey

    • 引用位置: 参数
  • ServerPlayer

    • 引用位置: 参数
  • Container

    • 引用位置: 参数/返回值
  • Entity

    • 引用位置: 参数
  • EquipmentSlot

    • 引用位置: 参数
  • ItemEntity

    • 引用位置: 构造调用
    • 关联成员: ItemEntity()
  • ItemInstance

    • 引用位置: 参数
  • ItemStack

    • 引用位置: 参数/方法调用/返回值
    • 关联成员: ItemStack.isSameItemSameComponents()
  • LootParams

    • 引用位置: 参数/方法调用/构造调用
    • 关联成员: Builder(), LootParams.Builder()
  • LootTable

    • 引用位置: 参数
  • Vec3

    • 引用位置: 参数/方法调用
    • 关联成员: Vec3.atCenterOf()