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

119 lines
8.8 KiB
Java

package net.minecraft.server.commands;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.properties.Property;
import java.util.Collections;
import net.minecraft.world.level.block.Blocks;
import com.mojang.brigadier.Message;
import net.minecraft.core.Vec3i;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import java.util.Iterator;
import net.minecraft.server.level.ServerLevel;
import java.util.List;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.Clearable;
import net.minecraft.world.level.LevelReader;
import net.minecraft.core.BlockPos;
import com.google.common.collect.Lists;
import javax.annotation.Nullable;
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import java.util.function.Predicate;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.commands.arguments.blocks.BlockPredicateArgument;
import net.minecraft.commands.arguments.blocks.BlockStateArgument;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.arguments.ArgumentType;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.commands.Commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import net.minecraft.commands.arguments.blocks.BlockInput;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
public class FillCommand {
private static final Dynamic2CommandExceptionType ERROR_AREA_TOO_LARGE;
private static final BlockInput HOLLOW_CORE;
private static final SimpleCommandExceptionType ERROR_FAILED;
public static void register(final CommandDispatcher<CommandSourceStack> commandDispatcher) {
commandDispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("fill").requires(cq -> cq.hasPermission(2))).then(Commands.argument("from", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).then(Commands.argument("to", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).then(((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)Commands.argument("block", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockStateArgument.block()).executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.REPLACE, null))).then(((LiteralArgumentBuilder)Commands.literal("replace").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.REPLACE, null))).then(Commands.argument("filter", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPredicateArgument.blockPredicate()).executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.REPLACE, BlockPredicateArgument.getBlockPredicate((CommandContext<CommandSourceStack>)commandContext, "filter")))))).then(Commands.literal("keep").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.REPLACE, byk -> byk.getLevel().isEmptyBlock(byk.getPos()))))).then(Commands.literal("outline").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.OUTLINE, null)))).then(Commands.literal("hollow").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.HOLLOW, null)))).then(Commands.literal("destroy").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.DESTROY, null)))))));
}
private static int fillBlocks(final CommandSourceStack cq, final BoundingBox cky, final BlockInput ds, final Mode a, @Nullable final Predicate<BlockInWorld> predicate) throws CommandSyntaxException {
final int integer6 = cky.getXSpan() * cky.getYSpan() * cky.getZSpan();
if (integer6 > 32768) {
throw FillCommand.ERROR_AREA_TOO_LARGE.create(32768, integer6);
}
final List<BlockPos> list7 = Lists.newArrayList();
final ServerLevel xd8 = cq.getLevel();
int integer7 = 0;
for (final BlockPos fk11 : BlockPos.betweenClosed(cky.x0, cky.y0, cky.z0, cky.x1, cky.y1, cky.z1)) {
if (predicate != null && !predicate.test(new BlockInWorld(xd8, fk11, true))) {
continue;
}
final BlockInput ds2 = a.filter.filter(cky, fk11, ds, xd8);
if (ds2 == null) {
continue;
}
final BlockEntity bwi13 = xd8.getBlockEntity(fk11);
Clearable.tryClear(bwi13);
if (!ds2.place(xd8, fk11, 2)) {
continue;
}
list7.add(fk11.immutable());
++integer7;
}
for (final BlockPos fk11 : list7) {
final Block bpe12 = xd8.getBlockState(fk11).getBlock();
xd8.blockUpdated(fk11, bpe12);
}
if (integer7 == 0) {
throw FillCommand.ERROR_FAILED.create();
}
cq.sendSuccess(new TranslatableComponent("commands.fill.success", new Object[] { integer7 }), true);
return integer7;
}
static {
ERROR_AREA_TOO_LARGE = new Dynamic2CommandExceptionType((object1, object2) -> new TranslatableComponent("commands.fill.toobig", new Object[] { object1, object2 }));
HOLLOW_CORE = new BlockInput(Blocks.AIR.defaultBlockState(), Collections.<Property<?>>emptySet(), null);
ERROR_FAILED = new SimpleCommandExceptionType((Message)new TranslatableComponent("commands.fill.failed", new Object[0]));
}
enum Mode {
REPLACE((cky, fk, ds, xd) -> ds),
OUTLINE((cky, fk, ds, xd) -> {
if (fk.getX() == cky.x0 || fk.getX() == cky.x1 || fk.getY() == cky.y0 || fk.getY() == cky.y1 || fk.getZ() == cky.z0 || fk.getZ() == cky.z1) {
return ds;
}
else {
return null;
}
}),
HOLLOW((cky, fk, ds, xd) -> {
if (fk.getX() == cky.x0 || fk.getX() == cky.x1 || fk.getY() == cky.y0 || fk.getY() == cky.y1 || fk.getZ() == cky.z0 || fk.getZ() == cky.z1) {
return ds;
}
else {
return FillCommand.HOLLOW_CORE;
}
}),
DESTROY((cky, fk, ds, xd) -> {
xd.destroyBlock(fk, true);
return ds;
});
public final SetBlockCommand.Filter filter;
private Mode(final SetBlockCommand.Filter a) {
this.filter = a;
}
}
}