520 lines
21 KiB
Java
520 lines
21 KiB
Java
package net.minecraft.server.commands;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.mojang.brigadier.CommandDispatcher;
|
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
|
import com.mojang.brigadier.context.CommandContext;
|
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import net.minecraft.commands.CommandBuildContext;
|
|
import net.minecraft.commands.CommandSourceStack;
|
|
import net.minecraft.commands.Commands;
|
|
import net.minecraft.commands.SharedSuggestionProvider;
|
|
import net.minecraft.commands.arguments.EntityArgument;
|
|
import net.minecraft.commands.arguments.ResourceOrIdArgument;
|
|
import net.minecraft.commands.arguments.SlotArgument;
|
|
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
|
|
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
|
|
import net.minecraft.commands.arguments.item.ItemArgument;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Holder;
|
|
import net.minecraft.core.registries.Registries;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.resources.ResourceKey;
|
|
import net.minecraft.server.ReloadableServerRegistries;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.world.Container;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EquipmentSlot;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.SlotAccess;
|
|
import net.minecraft.world.entity.item.ItemEntity;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.storage.loot.LootParams;
|
|
import net.minecraft.world.level.storage.loot.LootTable;
|
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
public class LootCommand {
|
|
public static final SuggestionProvider<CommandSourceStack> SUGGEST_LOOT_TABLE = (commandContext, suggestionsBuilder) -> {
|
|
ReloadableServerRegistries.Holder holder = commandContext.getSource().getServer().reloadableRegistries();
|
|
return SharedSuggestionProvider.suggestResource(holder.getKeys(Registries.LOOT_TABLE), suggestionsBuilder);
|
|
};
|
|
private static final DynamicCommandExceptionType ERROR_NO_HELD_ITEMS = new DynamicCommandExceptionType(
|
|
object -> Component.translatableEscape("commands.drop.no_held_items", object)
|
|
);
|
|
private static final DynamicCommandExceptionType ERROR_NO_ENTITY_LOOT_TABLE = new DynamicCommandExceptionType(
|
|
object -> Component.translatableEscape("commands.drop.no_loot_table.entity", object)
|
|
);
|
|
private static final DynamicCommandExceptionType ERROR_NO_BLOCK_LOOT_TABLE = new DynamicCommandExceptionType(
|
|
object -> Component.translatableEscape("commands.drop.no_loot_table.block", object)
|
|
);
|
|
|
|
public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) {
|
|
dispatcher.register(
|
|
addTargets(
|
|
Commands.literal("loot").requires(commandSourceStack -> commandSourceStack.hasPermission(2)),
|
|
(argumentBuilder, dropConsumer) -> argumentBuilder.then(
|
|
Commands.literal("fish")
|
|
.then(
|
|
Commands.argument("loot_table", ResourceOrIdArgument.lootTable(context))
|
|
.suggests(SUGGEST_LOOT_TABLE)
|
|
.then(
|
|
Commands.argument("pos", BlockPosArgument.blockPos())
|
|
.executes(
|
|
commandContext -> dropFishingLoot(
|
|
commandContext,
|
|
ResourceOrIdArgument.getLootTable(commandContext, "loot_table"),
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
|
ItemStack.EMPTY,
|
|
dropConsumer
|
|
)
|
|
)
|
|
.then(
|
|
Commands.argument("tool", ItemArgument.item(context))
|
|
.executes(
|
|
commandContext -> dropFishingLoot(
|
|
commandContext,
|
|
ResourceOrIdArgument.getLootTable(commandContext, "loot_table"),
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
|
ItemArgument.getItem(commandContext, "tool").createItemStack(1, false),
|
|
dropConsumer
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("mainhand")
|
|
.executes(
|
|
commandContext -> dropFishingLoot(
|
|
commandContext,
|
|
ResourceOrIdArgument.getLootTable(commandContext, "loot_table"),
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
|
getSourceHandItem(commandContext.getSource(), EquipmentSlot.MAINHAND),
|
|
dropConsumer
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("offhand")
|
|
.executes(
|
|
commandContext -> dropFishingLoot(
|
|
commandContext,
|
|
ResourceOrIdArgument.getLootTable(commandContext, "loot_table"),
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
|
getSourceHandItem(commandContext.getSource(), EquipmentSlot.OFFHAND),
|
|
dropConsumer
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("loot")
|
|
.then(
|
|
Commands.argument("loot_table", ResourceOrIdArgument.lootTable(context))
|
|
.suggests(SUGGEST_LOOT_TABLE)
|
|
.executes(commandContext -> dropChestLoot(commandContext, ResourceOrIdArgument.getLootTable(commandContext, "loot_table"), dropConsumer))
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("kill")
|
|
.then(
|
|
Commands.argument("target", EntityArgument.entity())
|
|
.executes(commandContext -> dropKillLoot(commandContext, EntityArgument.getEntity(commandContext, "target"), dropConsumer))
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("mine")
|
|
.then(
|
|
Commands.argument("pos", BlockPosArgument.blockPos())
|
|
.executes(commandContext -> dropBlockLoot(commandContext, BlockPosArgument.getLoadedBlockPos(commandContext, "pos"), ItemStack.EMPTY, dropConsumer))
|
|
.then(
|
|
Commands.argument("tool", ItemArgument.item(context))
|
|
.executes(
|
|
commandContext -> dropBlockLoot(
|
|
commandContext,
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
|
ItemArgument.getItem(commandContext, "tool").createItemStack(1, false),
|
|
dropConsumer
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("mainhand")
|
|
.executes(
|
|
commandContext -> dropBlockLoot(
|
|
commandContext,
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
|
getSourceHandItem(commandContext.getSource(), EquipmentSlot.MAINHAND),
|
|
dropConsumer
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("offhand")
|
|
.executes(
|
|
commandContext -> dropBlockLoot(
|
|
commandContext,
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
|
getSourceHandItem(commandContext.getSource(), EquipmentSlot.OFFHAND),
|
|
dropConsumer
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
private static <T extends ArgumentBuilder<CommandSourceStack, T>> T addTargets(T builder, LootCommand.TailProvider tailProvider) {
|
|
return builder.then(
|
|
Commands.literal("replace")
|
|
.then(
|
|
Commands.literal("entity")
|
|
.then(
|
|
Commands.argument("entities", EntityArgument.entities())
|
|
.then(
|
|
tailProvider.construct(
|
|
Commands.argument("slot", SlotArgument.slot()),
|
|
(commandContext, list, callback) -> entityReplace(
|
|
EntityArgument.getEntities(commandContext, "entities"), SlotArgument.getSlot(commandContext, "slot"), list.size(), list, callback
|
|
)
|
|
)
|
|
.then(
|
|
tailProvider.construct(
|
|
Commands.argument("count", IntegerArgumentType.integer(0)),
|
|
(commandContext, list, callback) -> entityReplace(
|
|
EntityArgument.getEntities(commandContext, "entities"),
|
|
SlotArgument.getSlot(commandContext, "slot"),
|
|
IntegerArgumentType.getInteger(commandContext, "count"),
|
|
list,
|
|
callback
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("block")
|
|
.then(
|
|
Commands.argument("targetPos", BlockPosArgument.blockPos())
|
|
.then(
|
|
tailProvider.construct(
|
|
Commands.argument("slot", SlotArgument.slot()),
|
|
(commandContext, list, callback) -> blockReplace(
|
|
commandContext.getSource(),
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "targetPos"),
|
|
SlotArgument.getSlot(commandContext, "slot"),
|
|
list.size(),
|
|
list,
|
|
callback
|
|
)
|
|
)
|
|
.then(
|
|
tailProvider.construct(
|
|
Commands.argument("count", IntegerArgumentType.integer(0)),
|
|
(commandContext, list, callback) -> blockReplace(
|
|
commandContext.getSource(),
|
|
BlockPosArgument.getLoadedBlockPos(commandContext, "targetPos"),
|
|
IntegerArgumentType.getInteger(commandContext, "slot"),
|
|
IntegerArgumentType.getInteger(commandContext, "count"),
|
|
list,
|
|
callback
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("insert")
|
|
.then(
|
|
tailProvider.construct(
|
|
Commands.argument("targetPos", BlockPosArgument.blockPos()),
|
|
(commandContext, list, callback) -> blockDistribute(
|
|
commandContext.getSource(), BlockPosArgument.getLoadedBlockPos(commandContext, "targetPos"), list, callback
|
|
)
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("give")
|
|
.then(
|
|
tailProvider.construct(
|
|
Commands.argument("players", EntityArgument.players()),
|
|
(commandContext, list, callback) -> playerGive(EntityArgument.getPlayers(commandContext, "players"), list, callback)
|
|
)
|
|
)
|
|
)
|
|
.then(
|
|
Commands.literal("spawn")
|
|
.then(
|
|
tailProvider.construct(
|
|
Commands.argument("targetPos", Vec3Argument.vec3()),
|
|
(commandContext, list, callback) -> dropInWorld(commandContext.getSource(), Vec3Argument.getVec3(commandContext, "targetPos"), list, 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> items, LootCommand.Callback callback) throws CommandSyntaxException {
|
|
Container container = getContainer(source, pos);
|
|
List<ItemStack> list = Lists.<ItemStack>newArrayListWithCapacity(items.size());
|
|
|
|
for (ItemStack itemStack : items) {
|
|
if (distributeToContainer(container, itemStack.copy())) {
|
|
container.setChanged();
|
|
list.add(itemStack);
|
|
}
|
|
}
|
|
|
|
callback.accept(list);
|
|
return list.size();
|
|
}
|
|
|
|
private static boolean distributeToContainer(Container container, ItemStack item) {
|
|
boolean bl = false;
|
|
|
|
for (int i = 0; i < container.getContainerSize() && !item.isEmpty(); i++) {
|
|
ItemStack itemStack = container.getItem(i);
|
|
if (container.canPlaceItem(i, item)) {
|
|
if (itemStack.isEmpty()) {
|
|
container.setItem(i, item);
|
|
bl = true;
|
|
break;
|
|
}
|
|
|
|
if (canMergeItems(itemStack, item)) {
|
|
int j = item.getMaxStackSize() - itemStack.getCount();
|
|
int k = Math.min(item.getCount(), j);
|
|
item.shrink(k);
|
|
itemStack.grow(k);
|
|
bl = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bl;
|
|
}
|
|
|
|
private static int blockReplace(CommandSourceStack source, BlockPos pos, int slot, int numSlots, List<ItemStack> items, LootCommand.Callback callback) throws CommandSyntaxException {
|
|
Container container = getContainer(source, pos);
|
|
int i = container.getContainerSize();
|
|
if (slot >= 0 && slot < i) {
|
|
List<ItemStack> list = Lists.<ItemStack>newArrayListWithCapacity(items.size());
|
|
|
|
for (int j = 0; j < numSlots; j++) {
|
|
int k = slot + j;
|
|
ItemStack itemStack = j < items.size() ? (ItemStack)items.get(j) : ItemStack.EMPTY;
|
|
if (container.canPlaceItem(k, itemStack)) {
|
|
container.setItem(k, itemStack);
|
|
list.add(itemStack);
|
|
}
|
|
}
|
|
|
|
callback.accept(list);
|
|
return list.size();
|
|
} else {
|
|
throw ItemCommands.ERROR_TARGET_INAPPLICABLE_SLOT.create(slot);
|
|
}
|
|
}
|
|
|
|
private static boolean canMergeItems(ItemStack first, ItemStack second) {
|
|
return first.getCount() <= first.getMaxStackSize() && ItemStack.isSameItemSameComponents(first, second);
|
|
}
|
|
|
|
private static int playerGive(Collection<ServerPlayer> targets, List<ItemStack> items, LootCommand.Callback callback) throws CommandSyntaxException {
|
|
List<ItemStack> list = Lists.<ItemStack>newArrayListWithCapacity(items.size());
|
|
|
|
for (ItemStack itemStack : items) {
|
|
for (ServerPlayer serverPlayer : targets) {
|
|
if (serverPlayer.getInventory().add(itemStack.copy())) {
|
|
list.add(itemStack);
|
|
}
|
|
}
|
|
}
|
|
|
|
callback.accept(list);
|
|
return list.size();
|
|
}
|
|
|
|
private static void setSlots(Entity target, List<ItemStack> items, int startSlot, int numSlots, List<ItemStack> setItems) {
|
|
for (int i = 0; i < numSlots; i++) {
|
|
ItemStack itemStack = i < items.size() ? (ItemStack)items.get(i) : ItemStack.EMPTY;
|
|
SlotAccess slotAccess = target.getSlot(startSlot + i);
|
|
if (slotAccess != SlotAccess.NULL && slotAccess.set(itemStack.copy())) {
|
|
setItems.add(itemStack);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static int entityReplace(Collection<? extends Entity> targets, int startSlot, int numSlots, List<ItemStack> items, LootCommand.Callback callback) throws CommandSyntaxException {
|
|
List<ItemStack> list = Lists.<ItemStack>newArrayListWithCapacity(items.size());
|
|
|
|
for (Entity entity : targets) {
|
|
if (entity instanceof ServerPlayer serverPlayer) {
|
|
setSlots(entity, items, startSlot, numSlots, list);
|
|
serverPlayer.containerMenu.broadcastChanges();
|
|
} else {
|
|
setSlots(entity, items, startSlot, numSlots, list);
|
|
}
|
|
}
|
|
|
|
callback.accept(list);
|
|
return list.size();
|
|
}
|
|
|
|
private static int dropInWorld(CommandSourceStack source, Vec3 pos, List<ItemStack> items, LootCommand.Callback callback) throws CommandSyntaxException {
|
|
ServerLevel serverLevel = source.getLevel();
|
|
items.forEach(itemStack -> {
|
|
ItemEntity itemEntity = new ItemEntity(serverLevel, pos.x, pos.y, pos.z, itemStack.copy());
|
|
itemEntity.setDefaultPickUpDelay();
|
|
serverLevel.addFreshEntity(itemEntity);
|
|
});
|
|
callback.accept(items);
|
|
return items.size();
|
|
}
|
|
|
|
private static void callback(CommandSourceStack source, List<ItemStack> items) {
|
|
if (items.size() == 1) {
|
|
ItemStack itemStack = (ItemStack)items.get(0);
|
|
source.sendSuccess(() -> Component.translatable("commands.drop.success.single", itemStack.getCount(), itemStack.getDisplayName()), false);
|
|
} else {
|
|
source.sendSuccess(() -> Component.translatable("commands.drop.success.multiple", items.size()), false);
|
|
}
|
|
}
|
|
|
|
private static void callback(CommandSourceStack source, List<ItemStack> items, ResourceKey<LootTable> lootTable) {
|
|
if (items.size() == 1) {
|
|
ItemStack itemStack = (ItemStack)items.get(0);
|
|
source.sendSuccess(
|
|
() -> Component.translatable(
|
|
"commands.drop.success.single_with_table", itemStack.getCount(), itemStack.getDisplayName(), Component.translationArg(lootTable.location())
|
|
),
|
|
false
|
|
);
|
|
} else {
|
|
source.sendSuccess(
|
|
() -> Component.translatable("commands.drop.success.multiple_with_table", items.size(), Component.translationArg(lootTable.location())), 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, ItemStack tool, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException {
|
|
CommandSourceStack commandSourceStack = context.getSource();
|
|
ServerLevel serverLevel = commandSourceStack.getLevel();
|
|
BlockState blockState = serverLevel.getBlockState(pos);
|
|
BlockEntity blockEntity = serverLevel.getBlockEntity(pos);
|
|
Optional<ResourceKey<LootTable>> optional = blockState.getBlock().getLootTable();
|
|
if (optional.isEmpty()) {
|
|
throw ERROR_NO_BLOCK_LOOT_TABLE.create(blockState.getBlock().getName());
|
|
} else {
|
|
LootParams.Builder builder = new LootParams.Builder(serverLevel)
|
|
.withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos))
|
|
.withParameter(LootContextParams.BLOCK_STATE, blockState)
|
|
.withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity)
|
|
.withOptionalParameter(LootContextParams.THIS_ENTITY, commandSourceStack.getEntity())
|
|
.withParameter(LootContextParams.TOOL, tool);
|
|
List<ItemStack> list = blockState.getDrops(builder);
|
|
return dropConsumer.accept(context, list, listx -> callback(commandSourceStack, listx, (ResourceKey<LootTable>)optional.get()));
|
|
}
|
|
}
|
|
|
|
private static int dropKillLoot(CommandContext<CommandSourceStack> context, Entity entity, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException {
|
|
Optional<ResourceKey<LootTable>> optional = entity.getLootTable();
|
|
if (optional.isEmpty()) {
|
|
throw ERROR_NO_ENTITY_LOOT_TABLE.create(entity.getDisplayName());
|
|
} else {
|
|
CommandSourceStack commandSourceStack = context.getSource();
|
|
LootParams.Builder builder = new LootParams.Builder(commandSourceStack.getLevel());
|
|
Entity entity2 = commandSourceStack.getEntity();
|
|
if (entity2 instanceof Player player) {
|
|
builder.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, player);
|
|
}
|
|
|
|
builder.withParameter(LootContextParams.DAMAGE_SOURCE, entity.damageSources().magic());
|
|
builder.withOptionalParameter(LootContextParams.DIRECT_ATTACKING_ENTITY, entity2);
|
|
builder.withOptionalParameter(LootContextParams.ATTACKING_ENTITY, entity2);
|
|
builder.withParameter(LootContextParams.THIS_ENTITY, entity);
|
|
builder.withParameter(LootContextParams.ORIGIN, commandSourceStack.getPosition());
|
|
LootParams lootParams = builder.create(LootContextParamSets.ENTITY);
|
|
LootTable lootTable = commandSourceStack.getServer().reloadableRegistries().getLootTable((ResourceKey<LootTable>)optional.get());
|
|
List<ItemStack> list = lootTable.getRandomItems(lootParams);
|
|
return dropConsumer.accept(context, list, listx -> callback(commandSourceStack, listx, (ResourceKey<LootTable>)optional.get()));
|
|
}
|
|
}
|
|
|
|
private static int dropChestLoot(CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, LootCommand.DropConsumer dropCOnsimer) throws CommandSyntaxException {
|
|
CommandSourceStack commandSourceStack = context.getSource();
|
|
LootParams lootParams = new LootParams.Builder(commandSourceStack.getLevel())
|
|
.withOptionalParameter(LootContextParams.THIS_ENTITY, commandSourceStack.getEntity())
|
|
.withParameter(LootContextParams.ORIGIN, commandSourceStack.getPosition())
|
|
.create(LootContextParamSets.CHEST);
|
|
return drop(context, lootTable, lootParams, dropCOnsimer);
|
|
}
|
|
|
|
private static int dropFishingLoot(
|
|
CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, BlockPos pos, ItemStack tool, LootCommand.DropConsumer dropConsumet
|
|
) throws CommandSyntaxException {
|
|
CommandSourceStack commandSourceStack = context.getSource();
|
|
LootParams lootParams = new LootParams.Builder(commandSourceStack.getLevel())
|
|
.withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos))
|
|
.withParameter(LootContextParams.TOOL, tool)
|
|
.withOptionalParameter(LootContextParams.THIS_ENTITY, commandSourceStack.getEntity())
|
|
.create(LootContextParamSets.FISHING);
|
|
return drop(context, lootTable, lootParams, dropConsumet);
|
|
}
|
|
|
|
private static int drop(CommandContext<CommandSourceStack> context, Holder<LootTable> lootTable, LootParams params, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException {
|
|
CommandSourceStack commandSourceStack = context.getSource();
|
|
List<ItemStack> list = lootTable.value().getRandomItems(params);
|
|
return dropConsumer.accept(context, list, listx -> callback(commandSourceStack, listx));
|
|
}
|
|
|
|
@FunctionalInterface
|
|
interface Callback {
|
|
void accept(List<ItemStack> list) throws CommandSyntaxException;
|
|
}
|
|
|
|
@FunctionalInterface
|
|
interface DropConsumer {
|
|
int accept(CommandContext<CommandSourceStack> commandContext, List<ItemStack> list, LootCommand.Callback callback) throws CommandSyntaxException;
|
|
}
|
|
|
|
@FunctionalInterface
|
|
interface TailProvider {
|
|
ArgumentBuilder<CommandSourceStack, ?> construct(ArgumentBuilder<CommandSourceStack, ?> argumentBuilder, LootCommand.DropConsumer dropConsumer);
|
|
}
|
|
}
|